알고리즘

[약수] 구하기(Kotlin)

Developer성현 2025. 1. 11. 01:35

약수: 어떤 수를 나누어 떨어지게 하는 수

예1) 8의 약수 -> 1, 2, 4, 8

예2) 12의 약수 -> 1, 2, 3, 4, 6, 12

 

1. Brute Force(완전탐색)

1 ~ n 까지 모든 수를 n 과 나눠보면서 판별합니다.

(방식1)

val n = 12
val divisors: MutableList<Int> = mutableListOf()
for (i in 1..n){
    if(n % i == 0){
        divisors.add(i)
    }
}
println(divisors.joinToString(", "))

 

(방식2)

val n = 12
val divisors = (1..n).filter { n % it == 0 }
println(divisors.joinToString(", "))

 

시간 복잡도: O(n)

 

2. 제곱근 범위탐색

약수는 항상 대칭으로 짝을 이루고 있습니다.

그래서 12의 약수[1, 2, 3, 4, 6, 12]  를 구한다고 했을 때 약수의 절반 인 1, 2, 3 만 구하여도

(12 / 1) = 12, (12 / 2) = 6, (12 / 3) = 4 이 됩니다. 그리고 약수의 절반은 제곱근 을 하면 구할 수 있습니다.(√(12) ≒ 3.464) 소수점은 버리시면 됩니다.

val n = 12
val divisors: MutableList<Int> = mutableListOf()
for (i in 1..sqrt(n.toDouble()).toInt()){
    if(n % i == 0){
        divisors.add(i)
        if(i != n / i){
            divisors.add(n / i)
        }
    }
}
divisors.sort()
println(divisors.joinToString(", "))

 

시간 복잡도: O(√(n))

 

3. 약수 미리계산

약수에는 규칙이 있습니다. 2 ~ n 모두 자기 자신의 수의 배수를 구하고 그 수의 약수를 보면 자기 자신의 수를 포함합니다.

2의 배수인 4, 6, 8, ... 의 약수를 구해보면

4: [1, 2, 4]

6: [1, 2, 3, 6]

8: [1, 2, 4, 8]

모두 2를 포함하고 있습니다. 3도 마찬가지 입니다. 3의 배수인 6, 9, 12 의 약수를 구해보면

6: [1, 2, 3, 6]

9: [1, 3, 9]

12: [1, 2, 3, 4, 6, 12]

로 모두 3을 포함하고 있습니다.

이 규칙을 활용해서 한번에 ~n 개의 약수를 구할 수 있습니다.

val limit = 10
val divisorsList = List(limit + 1) { mutableListOf<Int>() }
for (i in 1..limit) {
    for (j in i..limit step i) {
        divisorsList[j].add(i)
    }
}
println(divisorsList)

 

시간 복잡도: O(n log n)

 

약수를 구하는 알고리즘 3개를 살펴보았습니다.

감사합니다.