1. 문제 설명
- 두 수를 입력받아 두 수의 최대공약수와 최소공배수를 반환하는 함수, solution을 완성해 보세요. 배열의 맨 앞에 최대공약수, 그다음 최소공배수를 넣어 반환하면 됩니다. 예를 들어 두 수 3, 12의 최대공약수는 3, 최소공배수는 12이므로 solution(3, 12)는 [3, 12]를 반환해야 합니다.
2. 제한 조건
- 두 수는 1이상 1000000이하의 자연수입니다.
3. 입출력 예
let output = solution(3, 12);
console.log(output); // [3, 12]
output = solution(2, 5);
console.log(output); // [1, 10]
4. 입출력 예 설명
- 입출력 예 #1: 위의 설명과 같습니다.
- 입출력 예 #2: 자연수 2와 5의 최대공약수는 1, 최소공배수는 10이므로 [1, 10]을 리턴해야 합니다.
5. 문제 풀이
function solution(n, m) {
const getMaxDivisor = (a, b) => {
if (b === 0) return a;
if (a > b) return getMaxDivisor(b, a % b);
else return getMaxDivisor(a, b % a);
}
const result = [];
result.push(getMaxDivisor(n, m));
result.push(n * m / result[0]);
return result;
}
6. 문제 풀이 해설
function solution(n, m) {
// 분석
// 1. 최대공약수
// 두 수 중 큰수를 작은수로 나누었을 때
// 나누어 떨어지면 -> 작은수가 최대공약수가 된다.
// 나누어 떨어지지 않으면 -> 여기에서 나온 나머지 값으로 작은수를 다시 나눈다.
// (즉 나머지 값이 작은수가 되고, 본래 작은수였던 값이 큰수가 되는 셈이다.)
// 이 과정을 반복하면 결국 나누어 떨어지게 되고,
// 나누어떨어졌을 시점의 나누기 시행 수(작은 수)가 최대공약수가 된다.
// 2. 최소공배수
// n * m을 앞서 구한 최대공약수로 나누면 최소공배수가 된다.
// 풀이
// 위 로직을 바탕으로 최대공약수를 구하는 함수를 구현하면 된다.
const getMaxDivisor = (a, b) => {
// 지속적으로 나누기 연산을 해야하기 때문에 재귀를 적용해주자.
// 우선 base case(탈출부: 마지막 최소 단위)를 구현한다.
// 나누어 떨어졌을 때, 연산을 시행한 수가 최대공약수이다.
/* ex) 두 수 a, b가 각각 4, 2라고 가정해본다면,
a(큰수) % b(작은수)는 0이기 때문에, 2(작은수)가 최대공약수가 된다. */
if (b === 0) return a;
// recursive case
// 나누어 떨어지지 않았을 때는, 나머지로 더 작은 수를 나눈다.
// 둘 중 더 작은 수를 나머지로 나누다보면 나머지가 0이 되는 순간이 온다.
// 즉, 결국 나누어 떨어졌을 때 (위의 base case의 b가 0이 될 때),
// 나누기 연산을 시행한 수를 리턴해주면 된다.
if (a > b) return getMaxDivisor(b, a % b);
else return getMaxDivisor(a, b % a);
}
// 결과 변수를 만들어 주고
const result = [];
// 최대공약수부터 구해서 넣어 주고, 그걸 활용해 최소공배수도 넣는다.
result.push(getMaxDivisor(n, m));
result.push(n * m / result[0]);
// 결과를 리턴한다.
return result;
}