Mục lục

Climbing Stairs

Bài toán 'Hello World' của Dynamic Programming. Các bước cơ bản để tư duy QHĐ.

Bài toán

Bạn đang leo một cầu thang. Cần n bước để lên tới đỉnh. Mỗi lần bạn có thể leo 1 bước hoặc 2 bước. Hỏi có bao nhiêu cách khác nhau để leo lên đỉnh?

Ví dụ:

text:
Input: n = 2
Output: 2
Cách: (1, 1), (2)

Input: n = 3
Output: 3
Cách: (1, 1, 1), (1, 2), (2, 1)

Phân Tích & Tiếp Cận

1. Identify DP Problem

Tại bậc thang thứ i, ta chỉ có thể đến đó từ bậc i-1 (bước 1 bước) hoặc bậc i-2 (bước 2 bước). Vậy số cách để đến bậc i chính là tổng số cách đến bậc i-1 cộng với số cách đến bậc i-2. Công thức truy hồi (Recurrence Relation): dp[i] = dp[i-1] + dp[i-2].

2. Base Cases

  • Bậc 0: 1 cách (đứng yên).
  • Bậc 1: 1 cách (từ 0 lên 1).
  • Bậc 2: 2 cách.

3. Space Optimization (Tối ưu không gian)

Ta thấy dp[i] chỉ phụ thuộc vào 2 giá trị trước đó. Vậy không cần lưu mảng n phần tử, chỉ cần 2 biến one (đại diện i-1) và two (đại diện i-2). Đây chính là dãy Fibonacci.

typescript:
function climbStairs(n: number): number {
    let one = 1; // Cách để đến bậc n-1
    let two = 1; // Cách để đến bậc n-2

    for (let i = 0; i < n - 1; i++) {
        const temp = one;
        one = one + two;
        two = temp;
    }

    return one;
}
  • Time Complexity: $O(n)$.
  • Space Complexity: $O(1)$.

Pattern Nhận Diện

  • Bài toán đếm số cách (Count ways).
  • Quyết định tại bước hiện tại phụ thuộc vào các bước ngay trước đó.
  • Cấu trúc con tối ưu (Optimal Substructure) & Bài toán con gối nhau (Overlapping Subproblems).
Quảng cáo
mdhorizontal