[C++]최대공약수 구하기(3가지 방법, 유클리드 호제법)
- 컴퓨터공학과/Programming
- 2020. 5. 5.
반응형
문제
최대 공약수 구하기
두 정수 a, b의 최대공약수를 구하는 함수 get_gcd()를 구현해보세요.
int get_gcd(int a, int b)
{
// 두 정수 a, b의 최대공약수를 구하는 함수를 구현할 것!
}
int main()
{
int gcd = get_gcd(26, 48);
cout << gcd << endl;
}
문제풀이
(1) [1, min(a, b) ] 범위에서 두 수 모두의 약수가 되는 값 중 최댓값을 구하는 방법
* 가장 단순하고 직관적인 방법
int get_gcd(int a, int b)
{
int max_div = 1; // 가장 큰 공약수를 저장할 변수
int range = min(a, b); // 두 수 중 작은 값까지만 조사
// i부터 공약수를 찾는다.
for (int i = 1; i <= range; i++)
{
// 두 수 모두의 약수일 경우
if (a % i == 0 && b % i == 0)
{
max_div = i; // 갱신 (i는 점점 증가하므로 range 끝까지 수행)
}
}
return max_div;
}
▶ 이는 두 정수 a, b에 대하여 O(min(a,b))의 시간 복잡도를 가짐
알고리즘 코딩시험에서 최대공약수를 구하는 문제를 이렇게 푼다면, 분명히 시간초과가 발생할 것이다. 조금 더 빠르게 할 수 없을까?
(2) 역순 탐색
[1, min(a, b)]부터 1까지 역순으로 탐색하여 가장 처음 발견된 공약수가 결국 최대 공약수가 됨
int get_gcd(int a, int b)
{
int max_div = 1; // 가장 큰 공약수를 저장할 변수
int range = min(a, b);// 두 수 중 작은 값까지만 조사
// i부터 공약수를 찾는다.
for (int i = range; i >= 1; i--)
{
// 두 수 모두의 약수일 경우
if (a % i == 0 && b % i == 0)
{
max_div = i; // 저장 후 탈출
break; // i는 점점 감소하므로, 더이상 볼 필요가 없다.
}
}
return max_div;
}
▶ 일반적인 경우에는 (1)보다는 빠르겠지만 최악의 경우(두 정수 a, b가 서로 소인 경우)에는 동일하게 모든 수를 검사하므로 결국 (1)과 같은 시간 복잡도를 보임
3) 유클리드 호제법
f(a, b) = gcd(a, b)라 하자.
이 때 a mod b = 0 이라면, f(a, b) = b임이 자명.
이 때 a mod b이 0이 아닌 경우, f(a, b) = f(b, a mod b)가 성립한다.
이를 유클리드 호제법이라고 함
// (1) 반복문을 이용한 방법
int gcd(int a, int b)
{
int mod = a % b;
while (mod > 0)
{
a = b;
b = mod;
mod = a % b;
}
return b;
}
// (2) 재귀 함수형
int gcd2(int a, int b)
{
if (a % b == 0)
return b;
else
return gcd2(b, a % b);
}
// (3) 삼항 연산자 축약형
int gcd3(int a, int b)
{
return (a % b == 0 ? b : gcd3(b, a % b));
}
▶ 정수 a와 b에 대하여 근사적으로 O( log2(min(a, b)) ) 시간복잡도를 가짐
반응형
그리드형
'컴퓨터공학과 > Programming' 카테고리의 다른 글
[고급 C++]조건 컴파일 / make (0) | 2020.10.19 |
---|---|
[고급 C++]C컴파일러와 C라이브러리(공유/정적/동적라이브러리) (0) | 2020.10.18 |
[C++] 누구나 쉽게, 리팩토링(클린코드)-⑤ NULL체크를 위한 널 객체 (0) | 2020.04.18 |
[C++] 객체지향 개념(객체/클래스/생성자) 및 헤더파일 분리 요약정리 (0) | 2020.04.13 |
[C++] 누구나 쉽게, 리팩토링(클린코드)-④ 상속 (개념과 특징) (0) | 2020.04.13 |