Seongwon Lim

[Python] 약수 개수 구하기 (시간복잡도 고려하기) 본문

Python

[Python] 약수 개수 구하기 (시간복잡도 고려하기)

limsw 2022. 11. 19. 13:20
반응형

서론

프로그래머스 문제를 풀다가 약수의 개수를 구하는 과정에서 시간초과가 발생한 적이 있었다.

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

약수의 개수를 구해야 하는 숫자가 크지 않다면 시간 제한 내에 문제를 해결할 수 있지만 그렇지 않은 경우 시간 초과에 걸릴 확률이 높아질 수 있다. 그래서 이번 글에서는 파이썬을 이용하여 약수의 개수를 구할 때 시간복잡도를 줄여 효율적으로 약수의 개수를 구하는 방법에 대해서 간단하게 알아보고자 한다.

단순 풀이

n = 100
count = 0

for i in range(1, n+1):
    if n % i == 0:
        count += 1
print(count) # 9
  • 첫번째 방법은 1부터 n까지 모든 숫자를 돌면서 n으로 나누어 떨어지는지 확인하는 방법이다.
  • 위 로직의 경우 시간복잡도는 O(N)을 가진다.

이번에는 시간복잡도를 고려한 로직을 살펴보자.

시간복잡도를 고려한 풀이

먼저, 로직을 이해하기 전에 약수가 가지고 있는 특징에 대해서 이해할 필요가 있다.

바로 자연수 N에 대해서 두 약수의 곱이 N이 되는 A와 B가 반드시 존재한다는 의미이다.

 

조금 더 쉽게 설명하면 자연수(N) = 약수(A) * 약수(B) 로 나타낼 수 있다는 것이다. 따라서 1부터 n까지 반복문을 돌지 않아도 되며, n의 제곱근까지 약수를 구하면 해당 약수들에 대한 짝이 되는 약수를 자동으로 구할 수 있다.

 

코드를 보며 이해해보자.

n = 100
count = 0

for i in range(1, int(n**0.5)+1):
    if i*i == n:
        count += 1
        continue

    if n % i == 0:
        count += 2 # 해당 약수의 짝에 대한 약수까지 카운트
    
print(count) # 9

 

i*i == n인 경우는 제곱 수인 경우이므로 이 때의 i는 짝이 존재하지 않기 때문에 +1을 해준다.

 

혹은 아래와 같이 코드를 구성할 수도 있다.

n = 100
count = 0

for i in range(1, int(n**0.5)+1):
    if n % i == 0:
        count += 1
        if i ** 2 != n:
            count += 1
  • 두번째 방법은 n의 제곱근까지 반복문을 돌며 그 때의 약수, 해당 약수에 대한 짝을 찾아 약수의 개수를 구하는 방법이다.
  • 위 로직의 경우 시간복잡도는 O(N^(1/2))을 가진다.
Comments