Level 1) 두 정수 사이의 합, 콜라츠 추측, 서울에서 김서방 찾기, 나누어 떨어지는 숫자 배열

Doozuu·2023년 2월 5일
0

프로그래머스 (JS)

목록 보기
40/183

📌 문제 1. 두 정수 사이의 합

문제 설명

두 정수 a, b가 주어졌을 때 a와 b 사이에 속한 모든 정수의 합을 리턴하는 함수, solution을 완성하세요.
예를 들어 a = 3, b = 5인 경우, 3 + 4 + 5 = 12이므로 12를 리턴합니다.

제한 조건

a와 b가 같은 경우는 둘 중 아무 수나 리턴하세요.
a와 b는 -10,000,000 이상 10,000,000 이하인 정수입니다.
a와 b의 대소관계는 정해져있지 않습니다.

입출력 예

a	b	return
3	5	12
3	3	3
5	3	12

풀이

일단 처음 생각나는 방식은 반복문으로 a부터 b까지 더하는 것이었다.
// a가 b보다 작으면 a부터 b까지 합
// b가 a보다 작으면 b부터 a까지 합

function solution(a, b) {
    let answer = 0;
    if(a === b){
      return a;   
    }else if(a < b){
      for(let i=a;i<=b;i++) answer+=i   
    }else if(a > b){
      for(let i=b;i<=a;i++) answer+=i   
    }
    return answer;
}

조금 더 효율적인 방식을 생각해보니, 각각의 합을 구해서 더 큰 값에서 작은 값을 빼면 되겠다는 생각이 들었다.(1부터 n까지의 합은 반복문을 안쓰고 공식으로 구할 수 있으니 시간복잡도가 낮아진다.)

function solution(a, b) {
    if(a === b) return a;
    let sumA = a*(a+1)/2;
    let sumB = b*(b+1)/2;
    return a > b ? sumA - sumB + b : sumB - sumA + a;
}

첫 번째 풀이 방식을 보완하면
Math.min() 과 Math.max()를 이용해 무조건 작은 수부터 큰 수까지 더하도록 하여 a, b 대소관계에 따라 식을 따로 세우지 않고도 풀 수 있다.

function adder(a, b, s = 0){
  for (var i = Math.min(a, b); i <= Math.max(a, b); i++) s += i;
  return s;
}

신박한 풀이

가우스공식을 이용해 간단하게 구할 수 있다.

공식 : (양 끝의 합) * (양 끝의 합의 개수) / 2

function adder(a, b){
    var result = 0
    return (a+b)*(Math.abs(b-a)+1)/2;
}



📌 문제 2. 콜라츠 추측

문제 설명

1937년 Collatz란 사람에 의해 제기된 이 추측은, 주어진 수가 1이 될 때까지 다음 작업을 반복하면, 모든 수를 1로 만들 수 있다는 추측입니다. 작업은 다음과 같습니다.

1-1. 입력된 수가 짝수라면 2로 나눕니다. 
1-2. 입력된 수가 홀수라면 3을 곱하고 1을 더합니다. 
2. 결과로 나온 수에 같은 작업을 1이 될 때까지 반복합니다. 

예를 들어, 주어진 수가 6이라면 6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1 이 되어 총 8번 만에 1이 됩니다. 위 작업을 몇 번이나 반복해야 하는지 반환하는 함수, solution을 완성해 주세요. 단, 주어진 수가 1인 경우에는 0을, 작업을 500번 반복할 때까지 1이 되지 않는다면 –1을 반환해 주세요.

제한 사항

입력된 수, num은 1 이상 8,000,000 미만인 정수입니다.

풀이

  1. num이 1인 경우 바로 0을 return한다.
  2. num이 1보다 큰 경우 while문을 통해 홀수면 3을 곱하고 1을 더하는 작업을, 짝수면 2로 나누는 작업을 해주고, 횟수를 셀 수 있도록 count를 증가시킨다.
  3. count가 500 보다 크면 -1을, 같거나 작으면 count를 return한다.
function solution(num) {
    if(num === 1) return 0;
    let count = 0;
    while(num > 1){
        num % 2 ? num = num * 3 + 1 : num /= 2;
        count++;
    }
    return count > 500 ? -1 : count;
}

500보다 크면 연산을 더 할 필요가 없으므로 while 조건식에 500에 대한 것을 추가시키고, 1에 대한 조건식은 마지막에 answer를 이용해 씀으로써 더 깔끔하게 나타낼 수도 있다.

function collatz(num) {
    var answer = 0;
    while(num !=1 && answer !=500){
        num%2==0 ? num = num/2 : num = num*3 +1;
    answer++;
  }
    return num == 1 ? answer : -1;
}

재귀를 이용하면 아래처럼 나타낼 수도 있다.

function collatz(num,count = 0) {
    return num == 1 ? (count >= 500 ? -1 : count) : collatz(num % 2 == 0 ? num / 2 : num * 3 + 1,++count);
}



📌 문제 3. 서울에서 김서방 찾기

문제 설명

String형 배열 seoul의 element중 "Kim"의 위치 x를 찾아, "김서방은 x에 있다"는 String을 반환하는 함수, solution을 완성하세요. seoul에 "Kim"은 오직 한 번만 나타나며 잘못된 값이 입력되는 경우는 없습니다.

제한 사항

seoul은 길이 1 이상, 1000 이하인 배열입니다.
seoul의 원소는 길이 1 이상, 20 이하인 문자열입니다.
"Kim"은 반드시 seoul 안에 포함되어 있습니다.
입출력 예
seoul return
["Jane", "Kim"] "김서방은 1에 있다"

풀이

indexOf를 이용해 찾은 위치를 저장해서 return 하면 된다.

function solution(seoul) {
    let location = seoul.indexOf("Kim");
    return `김서방은 ${location}에 있다`;
}



📌 문제 4. 나누어 떨어지는 숫자 배열

문제 설명

array의 각 element 중 divisor로 나누어 떨어지는 값을 오름차순으로 정렬한 배열을 반환하는 함수, solution을 작성해주세요.
divisor로 나누어 떨어지는 element가 하나도 없다면 배열에 -1을 담아 반환하세요.

제한사항

arr은 자연수를 담은 배열입니다.
정수 i, j에 대해 i ≠ j 이면 arr[i] ≠ arr[j] 입니다.
divisor는 자연수입니다.
array는 길이 1 이상인 배열입니다.

입출력 예

arr				divisor		return
[5, 9, 7, 10]	5			[5, 10]
[2, 36, 1, 3]	1			[1, 2, 3, 36]
[3,2,6]			10			[-1]

풀이

나누어 떨어지는 것만 filter해주고 정렬한 뒤에 비어있으면 [-1]을, 아니면 answer를 return한다.

function solution(arr, divisor) {
    let answer = arr.filter(n => n % divisor === 0).sort((a,b) => a-b);
    return answer.length == 0 ? [-1] : answer;
}

정렬을 나중에 해줘도 된다.

function solution(arr, divisor) {
    var answer = arr.filter(v => v%divisor == 0);
    return answer.length == 0 ? [-1] : answer.sort((a,b) => a-b);
}
profile
모든게 새롭고 재밌는 프론트엔드 새싹

0개의 댓글