이 블로그의 모든 예제코드는 깃허브에서도 볼 수 있습니다. https://github.com/AeroCodeX/
성능은 중요해 |
아무런 고려없이 약수 알고리즘을 만든다면 아래와 같지 않을까.
아무리 심플한게 좋다지만, 이건 좀 과한 듯 싶다.
이 심플한 알고리즘은 v = 1,000,000,000
기준으로 평균 4208 ms
가 걸렸으며,
전체 연산량이 입력값에 대해 선형으로 증가하므로, 시간복잡도는 O(n)
이다.
입력값이 작은 상황에서는 괜찮겠지만, 입력값이 크거나 타임 크리티컬한 상황에서는 절대 사용하면 안된다.
상당한 개선이 필요해보인다.
음.. 전체 연산량을 줄일 수 있는 방법은 없을까?
있다. 약수의 정의를 생각하면 좀 더 빠르게 동작하는 약수 알고리즘을 구현할 수 있다.
정수 V, A, B에 대하여 위의 등식이 성립하면 A, B는 V의 약수라고 한다.
여기서 좀 더 생각해보자.
A가 증가하면 등식을 맞추기 위해 B는 감소할 것이고,
A와 B가 같은 값을 가질 때 교차할것이며,
교차점을 기준으로 y축 대칭이다.
정리하자면, V의 제곱근을 넘어서 얻은 해답은 중복이라는 것이다.
예를 들면 아래와 같은 상황이다.
(A, B) -------- (V, V) -------- (B, A) // 입력값이 V^2 일 때,
(2, 8) -------- (4, 4) -------- (8, 2) // 입력값이 16일 때,
자, 제곱근 이후의 해답은 중복임을 알았기 때문에 검사해야 할 범위가 루트 수준으로 줄었다.
위의 키 포인트를 이용해서 더욱 빠른 약수 알고리즘을 구현해보자.
C++에서 기본적으로 제공하는 sqrt 함수가 있지만,
입력을 정수로 한정지으면 9행처럼 구현하는 것이 훨씬 빠르다.
위 함수는 v = 1,000,000,000
기준으로 평균 0.328 ms
가 걸린다.
제곱근 까지만 조사하므로, 시간 복잡도 또한 O(log n)
이다!
'# Foundation > 기초수학' 카테고리의 다른 글
피보나치 수열 알고리즘 (0) | 2018.11.03 |
---|---|
소수 알고리즘 (0) | 2018.10.26 |
최대 공약수와 최소 공배수의 관계 (0) | 2018.10.24 |
최소 공배수 알고리즘 (0) | 2018.10.23 |
최대 공약수 알고리즘 (0) | 2018.10.22 |