결론
// 최대공약수 const gcd = (a, b) => a % b ? gcd(b, a % b) : b; // 최소공배수 const lcm = (a, b) => a * b / gcd(a, b);
최대공약수(Greatest Common Divisor, GCD)
: 두 수 이상의 여러 공약수 중 최대인 수
약수(Divisor) : 주어진 수를 나누어 떨어지게 하는 수
공약수(CD: Common Divisor) : 두 수 이상의 여러 수 중 공통된 약수.
6의 약수: 1, 2, 3, 6
9의 약수: 1, 3, 9
let gcd = (num1, num2) => {
let gcd = 1;
for(let i=2; i<=Math.min(num1, num2); i++){
if(num1 % i === 0 && num2 % i === 0){
gcd = i;
}
}
return gcd;
}
최소공배수(Lowest Common Multiple, LCM)
: 두 수 이상의 여러 공배수 중 최소인 수
12의 배수 : 12, 24, 36, 48, 60, 72, 84 ...
18의 배수 : 18, 36, 72, 90 ...
최대공약수를 구할 때 밑처럼 소인수분해로 구할 수 있다.
문제는 모든 정수를 나눠야해서 시간복잡도가 O(N)이 된다.
그리고 수가 클 때 계산이 복잡해져서 약수를 한번에 찾기 힘들어진다.
그럴 때 유클리드 호제법으로 빠르게 최대공약수를 구할 수 있다.
1. 나누는 수들을 모두 곱하면 288이 나오고 288이 최대 공약수다.
2. 최대공약수에 더이상 안나눠지는 밑 8, 5까지 다 곱하면 최소공배수가 나온다. (288 X 8 X 5)
두 자연수의 최대공약수를 빠르게 구하는 알고리즘
시간 복잡도 : O(log N)
9/6 = 1 + 3
6/3 = 2 + 0
=> 나머지가 0일때 나누는 수 3이 최대공약수
b가 0이 아니면 반복문실행, b가 0이면 a(이전반복에서의 a%b)반환
function gcd(a, b){
while(b !== 0){
let r = a % b;
a = b;
b = r;
}
return a;
}
나머지가 있으면 재귀함수 실행, 나머지가 없으면 나누는 수가 최대공약수.
const gcd = (a, b) => a % b ? gcd(b, a % b) : b;
최소공배수 * 최대공약수 = a * b
이 공식 이용해 밑처럼 구현하기
최소공배수 = a * b / 최대공약수
const lcm = (a, b) => a * b / gcd(a, b);