728x90
https://school.programmers.co.kr/learn/courses/30/lessons/12980#
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제 풀이
1 부터 12 까지 직접 계산한 결과 규칙이 있는것을 확인했다.
- 2로 나눠지면 나눈값에 해당하는 인덱스의 값을 사용
- 나머지가 있으면 바로 이전 인덱스의 값에 +1
해당 규칙을 찾고서 DP 문제라고 생각해 코드를 작성했다.
실패한 DP 방식
결론부터 말하자면 DP 방식은 효율성 점수 0점.
다른 방식을 사용해야한다.
func solution(_ n:Int) -> Int {
var arr = [0, 1, 1]
guard n > 2 else { return arr[n] }
for i in 3...n {
if i % 2 == 0 {
arr.append(arr[i / 2])
}
else {
arr.append(arr[i-1] + 1)
}
}
return arr[n]
}
아무래도 10억 이하의 자연수를 범위로 잡고 있기에, 높은 숫자를 다 체크하면서 제한시간을 초과하는것 같다.
그래서 다른 방식을 고민해봤다.
통과한 방식 (그리디? 비트 카운팅?)
func solution(_ n:Int) -> Int {
var n = n
var ans = 1
while n > 1 {
if n % 2 == 0 {
n /= 2
}
else {
n -= 1
ans += 1
}
}
return ans
}
처음부터 계산하는게 아닌 N부터 0으로 가는 스텝을 계산한 방식이다.
나머지가 있으면 한 걸음, 없으면 텔레포트 하는 방식
위 방식으로 효율성 점수까지 통과했다.
나누기를 최대한 활용하니까 스킵하는 스텝수가 많아져 효율성을 통과할 수 있었다.
그런데, 풀이를 보고나니 살짝 이상했다. 이거 비트 카운팅 할때랑 비슷한데?
그래서 몇 개 테스트케이스의 값을 이진수로 바꿔 비트가 1인 갯수만 세어보니 결과와 똑같았다..
간단한 다른 해결 방법
func solution(_ n:Int) -> Int {
return n.nonzeroBitCount
}
결국 스위프트 내장 메서드인 nonzeroBitCount 를 써서 해결 할 수도 있었다.
728x90