❓ 제목
숫자나라 기사단의 각 기사에게는 1번부터 number까지 번호가 지정되어 있습니다. 기사들은 무기점에서 무기를 구매하려고 합니다. 각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매하려 합니다. 단, 이웃나라와의 협약에 의해 공격력의 제한수치를 정하고, 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약기관에서 정한 공격력을 가지는 무기를 구매해야 합니다.
(중략)
기사단원의 수를 나타내는 정수 number와 이웃나라와 협약으로 정해진 공격력의 제한수치를 나타내는 정수 limit와 제한수치를 초과한 기사가 사용할 무기의 공격력을 나타내는 정수 power가 주어졌을 때, 무기점의 주인이 무기를 모두 만들기 위해 필요한 철의 무게를 return 하는 solution 함수를 완성하시오.
💡 풀이
import kotlin.math.sqrt
class Solution {
fun solution(number: Int, limit: Int, power: Int): Int {
var answer: Int = 0
for (i in 1 .. number) {
// 0부터 i의 제곱근까지 나누어 떨어지는 수들이 나옴
val x = (1..sqrt(i.toFloat()).toInt()).filter { i % it == 0 }
val cnt = (x + x.map{i/it}).toSet().count()
if(cnt > limit) answer += power else answer += cnt
// var cnt: Int = 0
// for(j: Int in 1..i) {
// if(i % j == 0) cnt ++
// }
// if(cnt > limit) answer += power else answer += cnt
}
return answer
}
}
약수는 제곱근을 기준으로 대칭을 이루고 있다. 약수의 개수가 홀수일 경우엔 제곱근을 포함하고 있으며, 짝수일 경우엔 제곱근이 포함되어있지 않다는 특징을 갖고 있다. 고로, 제곱근을 활용해 문제를 풀어야한다!
- 0부터 i의 제곱근까지 나누어 떨어지는 수들이 나오는 식을 x로 선언한다.
- x + x.map{i/it}으로 약수를 구하고 toSet으로 중복을 없앤 뒤 count로 개수를 센다.
- x.map{i/it}은 제곱근이 다시 나누어떨어지는지 판단하는 식이다. (제곱근을 기준으로 대칭을 이루고 있기 때문에 제곱근까지만 i로 나누어 수가 떨어지면 되기 때문이다.)
- 만약 cnt가 limit보다 크면 power를 더하고 그렇지 않으면 cnt 자체를 더한다.
2번 풀이해서 x와 x.map{i/it}, 그리고 x + x.map{i/it}의 결과값을 print로 찍어보면 아래와 같이 나온다.
x는 제곱근까지의 약수인 것이고, x.map{i/it}은 그 약수가 다시 i로 나눈 값이다. x + x.map{i/it}은 앞의 두 수를 합친 결과다.
주석처리한 풀이처럼 문제를 풀게 되면 시간 복잡도로 인해 무조건 런타임 에러가 나게 되어있다.
약수를 구하는 것 자체는 어렵지 않았는데 이를 제곱근까지 활용해가며 문제를 풀려고 하니 정말 머리가 깨질 듯이 아팠다...
❗출처
참고 사이트 : https://kdw999.tistory.com/40
'코딩테스트' 카테고리의 다른 글
[프로그래머스] 성격 유형 검사하기 (Kotlin) (0) | 2024.07.11 |
---|---|
[프로그래머스] 옹알이 (2) (Kotlin) (0) | 2024.06.26 |
[프로그래머스] 모의고사 (Kotlin) (0) | 2024.06.21 |
[프로그래머스] 행렬의 곱셈 (Kotlin) (0) | 2024.06.20 |
[프로그래머스] 과일 장수 (Kotlin) (0) | 2024.06.18 |