[프로그래머스] 점프와 순간 이동
문제
제한
- 주어지지 않음
입력
- 아이언 슈트 구매자가 이동하려는 거리 N
- 1 <= N <= 10억 (자연수)
출력
- 사용해야 하는 건전지 사용량의 최솟값
규칙
- K칸 점프
- 1 <= K (자연수)
- K만큼 건전지 사용
- 현재까지 거리 * 2 위치로 순간이동
- 건전지 사용 X
재구성
입력
- 만들어야 할 수 N
출력
- 0에서 N을 만드는 여러 방법 중, “더하는 수의 총합”이 최소가 되도록 하는 방법에서의 더하는 수의 총합
규칙
- +K
- cost: K
- *2
- cost: 0
접근
규칙 2에서 힌트를 얻을 수 있는데, 곱하기 2는 이진법에서 shift 연산이다. 따라서 앞으로 수를 이진법으로 다룰 것이다.
+K
는 +1
과 *2
연산을 사용하여 쪼갤 수 있다.
예를 들어,
K의 일의 자리수가 0이면
K = K' * 2
K의 일의 자리수가 0 또는 1이면
K = K' + 1
이때 비용은 다음과 같이 계산할 수 있다.
+K의 비용을 cost(K)라고 하자. 이 값은 규칙에 따라 K이다.
K의 일의 자리수가 0이면 K = K' * 2 인 K'가 존재한다
cost(K' * 2) = cost(K') = K / 2 이고 따라서
cost(K') = K / 2
K의 일의 자리수가 0 또는 1이면 K = K' + 1인 K'가 존재한다
cost(K' + 1) = cost(K') + 1 = K 이고 따라서
cost(K') = K - 1
쪼갤 수록 비용이 낮아지므로 최대한 쪼개는 것이 유리하다. 또한 비용이 더 많이 낮아지는 것은 K = K' * 2
일때 이므로, K
의 일의 자리수가 0이면 무조건 이를 적용하여야 한다. 따라서 쪼개는 규칙은 다음과 같이 정하는 것이 최적이다.
K의 일의 자리수가 0이면
K = K' * 2
K의 일의 자리수가 1이면
K = K' + 1
0에서 N을 만드는 가장 간단한 방법은 규칙 1을 사용하는 것이다.
0 + N
cost: N
여기서 +N
을 규칙에 따라 +1
과 *2
로 최대한 쪼개면 답을 얻을 수 있다.
예를 들어 1101
을 쪼개보자.
0 + 1101
1101 = 1100 + 1 # cost(1101) = cost(1100 + 1) = cost(1100) + 1
1100 = 110 * 2 # cost(1100) = cost(110 * 2) = cost(110)
110 = 11 * 2 # cost(110) = cost(11 * 2) = cost(11)
11 = 10 + 1 # cost(11) = cost(10 + 1) = cost(10) + 1
10 = 1 * 2 # cost(10) = cost(1 * 2) = cost(1)
1 = 0 + 1 # cost(1) = cost(0 + 1) = cost(0) + 1
cost: 3
그런데 규칙을 따라 쪼개보면 일의 자리수가 0인 경우 누적되는 비용이 없고, 일의 자리수가 1이면 1만큼 누적되는 것을 볼 수 있다. 따라서 굳이 재귀할 필요 없이 답을 구할 수 있다. 답은 N을 이진법으로 나타낼 때 ‘1’의 개수가 된다.
구현
def solution(n):
return bin(n).count('1')
댓글남기기