12980. 점프와 순간 이동

2026-04-02
프로그래머스 12980번 풀이

문제

점프와 순간 이동

풀이

아이디어

문제에서 너무 익숙한 DP의 맛이 나서 그냥 아무 생각 없이 Bottom-Up으로 풀었다. (사람은 생각을 하며 살아야 한다…) 시간초과가 나서 왜인가 봤더니 N이 최대 10억이어서 O(N) 풀이가 불가능했다.

그래서 Top-Down으로 풀이 방향을 바꿨다. 목적지 N에서 거꾸로 거슬러 올라가면 두 가지 경우로 나뉜다.

  • 짝수: N/2 위치에서 순간이동해서 왔을 것 → 배터리 소모 없음
  • 홀수: N-1 위치에서 1칸 점프해서 왔을 것 → 배터리 1 소모

이 규칙을 재귀로 적용하면 N을 계속 절반으로 줄여가며 홀수일 때만 카운트하면 된다.

메모이제이션은 DP답게 Array를 이용했다.

const usage = new Array(n + 1).fill(0);

그런데!!! 자꾸 시간초과가 발생하는것이다… 대체 O(log N)보다 어떻게 줄여야 하는 것이냐 하며 머리를 싸맸는데 알고보니 메모리 초과 문제였다. N이 최대 10억이기 때문에… 메모이제이션 배열에 드는 O(N)공간 역시 너무 컸던 것이다.

사실 Top-Down이기 때문에 모든 값을 메모할 필요는 없다. 따라서 배열 대신 Map을 이용해서 필요한 값만 메모하도록 수정했다. 그러자 시간초과도 해결되었다.

코드

function solution(n) {
  const usage = new Map();
  usage.set(0, 0);
  usage.set(1, 1); // 1칸 점프

  function go(i) {
    if (usage.get(i) !== undefined) return usage.get(i);
    if (i % 2 === 0) usage.set(i, go(i / 2));
    else usage.set(i, go(i - 1) + 1);
    return usage.get(i);
  }

  return go(n);
}

시간 / 공간 복잡도

  • 시간 복잡도: O(log N) - N을 절반씩 나누며 재귀 호출하므로
  • 공간 복잡도: O(log N) - Map에 저장되는 항목 수가 재귀 깊이에 비례

풀이 2

아이디어

풀이 1의 규칙을 다시 보면:

  • 짝수 → N/2로 이동 (비용 0)
  • 홀수 → N-1로 이동 (비용 1)

이 과정은 N을 오른쪽으로 1비트씩 시프트하는 것과 동일하다. 홀수일 때, 즉 최하위 비트가 1일 때만 비용이 발생한다. 결국 N의 이진수 표현에서 1의 개수가 정답이다.

예: N = 11 (1011₂) → 1이 3개 → 배터리 3

코드

function solution(n) {
  return n.toString(2).split('').filter((b) => b === '1').length;
}

시간 / 공간 복잡도

  • 시간 복잡도: O(log N) - 이진수 변환에 O(log N)
  • 공간 복잡도: O(log N) - 이진수 문자열 길이

여담

풀이 2는 “2배 텔레포트 계열” 문제를 풀 때 자주 나오는 패턴이라고 한다. 확실히 메모이제이션하는 것 보다는 간단하고 효율적인 방식이기 때문에 잘 기억해두는게 좋겠다.