Coding Test/LeetCode

70. Climbing Stairs

JTB 2025. 10. 13. 17:42
  • 난이도: 쉬움 (Easy)
  • 링크: LeetCode 70
  • 풀이 날짜: 2025.10.13

1. 문제 이해

한 번에 1계단 또는 2계단을 오를 수 있을 때, n개의 계단을 오르는 서로 다른 방법의 총 수를 구하는 문제이다.

 

예를 들어,

  • n = 2 → (1+1, 2) → 총 2가지
  • n = 3 → (1+1+1, 1+2, 2+1) → 총 3가지

즉, n번째 계단에 도달하는 방법은

(n-1)번째에서 한 칸, 또는 (n-2)번째에서 두 칸 올라오는 경우의 합이다.

한번더 풀어서 설명하면, n-1 번째까지 오르는 경우의 수 + n-2 번째까지 오는 경우의 수 를 합하면 n번째에 오르는 경우의 수인 것이다.

점화식은 dp[i] = dp[i-1] + dp[i-2] 이다.

 

2. 접근 아이디어 및 자료구조

이 문제는 1차원 DP(1Dimensional Dynamic Programming) 로 해결할 수 있다.

즉, 각 계단마다 “해당 계단까지 오르는 경우의 수”를 저장하면서 앞선 두 계단의 값을 더해가는 방식이다.

  • dp[i] = i번째 계단까지의 방법 수
  • dp[1] = 1, dp[2] = 2
  • 이후 dp[i] = dp[i-1] + dp[i-2]

이 문제는 이전 두 값만 알면 되므로, 배열 전체를 쓸 필요 없이 변수 2개만으로 최적화할 수 있다.

 

DP

여기에서 DP(Dynamic Programming, 동적 프로그래밍)는 복잡한 문제를 더 작은 하위 문제(subproblem)로 나누고,

그 결과를 저장(Memoization) 해가며 전체 문제를 효율적으로 해결하는 알고리즘 기법이다.

 

아래의 풀이코드에서 first, second 변수는 DP 배열의 압축판이라 할 수 있는데,

전형적인 DP 풀이라면 아래와 같이 dp 배열을 만들지만, 이렇게 하면 O(n) 공간이 필요하다.

dp[1] = 1;
dp[2] = 2;
for(let i=3; i<=n; i++){
    dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];

대신에, firstsecond 변수를 사용하면, 배열 대신 마지막 두 단계의 값만 저장해서 공간을 O(1)로 최적화한 형태가 된다.

즉, 배열을 쓰지 않고 메모이제이션(Memoization) 효과만 유지한 것이라서 여전히 DP라고 부를 수 있다.

 

3. 풀이 코드

var climbStairs = function(n) {
  if (n <= 2) return n; // 2이하인 경우, early return.

  let first = 1, second = 2;

  for (let i = 3; i <= n; i++) {
    const third = first + second;
    // 다음 계단으로 진행되기 때문에, 
    first = second; // first 는 second 값이,
    second = third; // second 는 가장 최근 값인 third 값이 할당된다.
  }

  return second; // 마지막 계단인 n 에서의 총 가지수 합인 third (first + second) 값이 할당되어 있다.
};
구분 복잡도 설명
시간 복잡도 O(n) n번 반복문 수행
공간 복잡도 O(1) 변수 3개만 사용

 

4. 정리 및 요약

포인트 설명
문제 유형 1D DP (피보나치 응용)
핵심 로직 dp[i] = dp[i-1] + dp[i-2]
메모리 최적화 배열 대신 변수 2개 사용
유사 문제 Fibonacci Number, House Robber, Min Cost Climbing Stairs

이 문제의 핵심은 “DP의 점화식을 이해하고, 공간을 최소화하는 것” 으로

결국 계단 오르기는 피보나치 수열의 형태로 귀결된다.

탐색이 아니라 누적 계산 문제이며, 반복문으로 간단히 처리할 수 있는 전형적인 1D DP 문제다.