Decode Ways dan Penghitungan Jalur
Selesaikan decode-ways (pemetaan digit ke huruf) sebagai DP mirip Fibonacci, lalu hitung jalur pada tangga dengan ukuran langkah variabel.
Decode Ways dan Penghitungan Jalur adalah pelajaran DSA Interview Prep gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar DSA Interview Prep, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus DSA Interview Prep mencakup 4 pelajaran total.
Masalah Cara Mendekode
Cara Mendekode (LeetCode 91) memetakan untaian digit ke huruf: 'A'=1, 'B'=2, ..., 'Z'=26. Dengan diberikan untaian digit berkode, hitung jumlah cara berbeda untuk mendekodenya. Sebagai contoh, '12' dapat didekode sebagai 'AB' (1+2) atau 'L' (12), sehingga ada 2 cara. '226' dapat menjadi 'BZ' (2+26), 'VF' (22+6), atau 'BBF' (2+2+6), sehingga ada 3 cara. Nol di awal membuat beberapa hasil dekode tidak valid.
# Encoding: A=1, B=2, ..., Z=26
# '12' → 'AB' or 'L' → 2 ways
# '226' → 'BZ' or 'VF' or 'BBF' → 3 ways
# '06' → invalid (no letter for '0')
# '10' → 'J' only → 1 way (only valid as 10, not 1+0)
s = '226'
print('Decodings for', s, ':', 3) # Expected: 3Formulasi DP untuk Cara Mendekode
Misalkan dp[i] = jumlah cara untuk mendekode s[:i]. Kasus dasar: dp[0] = 1 (untaian kosong, satu cara), dan dp[1] = 1 jika s[0] != '0', selain itu 0. Transisi: jika s[i-1] != '0', tambahkan dp[i-1] (dekode satu digit). Jika 10 ≤ int(s[i-2:i]) ≤ 26, tambahkan dp[i-2] (dekode dua digit). Ini pada dasarnya adalah pola Fibonacci dengan pemeriksaan validitas.
def num_decodings(s):
n = len(s)
dp = [0] * (n + 1)
dp[0] = 1 # empty prefix
dp[1] = 0 if s[0] == '0' else 1
for i in range(2, n + 1):
# Single digit decode
if s[i-1] != '0':
dp[i] += dp[i-1]
# Two digit decode
two_digit = int(s[i-2:i])
if 10 <= two_digit <= 26:
dp[i] += dp[i-2]
return dp[n]
print(num_decodings('12')) # 2
print(num_decodings('226')) # 3
print(num_decodings('06')) # 0Jebakan Angka Nol di Awal
Bagian tersulit dari Cara Mendekode adalah menangani angka nol. '0' yang berdiri sendiri tidak dapat didekode (tidak ada huruf yang dipetakan ke 0), jadi jika s[i-1] == '0', jangan tambahkan dp[i-1]. '0' sebagai digit kedua hanya valid jika bilangan dua digitnya adalah 10 atau 20. '30' atau '40' (dan bilangan yang lebih besar) tidak valid karena melebihi 26. Selalu periksa 10 ≤ two_digit ≤ 26, bukan hanya two_digit ≤ 26.
def num_decodings(s):
if not s or s[0] == '0': return 0
n = len(s)
dp = [0] * (n + 1)
dp[0] = 1
dp[1] = 1 # s[0] != '0' guaranteed by guard above
for i in range(2, n + 1):
one = int(s[i-1])
two = int(s[i-2:i])
if one != 0: dp[i] += dp[i-1] # valid single digit
if 10 <= two <= 26: dp[i] += dp[i-2] # valid two digits
return dp[n]
print(num_decodings('10')) # 1 (only 'J')
print(num_decodings('30')) # 0 (30 > 26, '0' alone invalid)
print(num_decodings('100')) # 0 (dp[2]=1 then '00' invalid, single '0' invalid)Cara Mendekode dengan Optimisasi Ruang
Seperti Fibonacci, relasi rekurensi jumlah cara mendekode hanya melihat dua posisi sebelumnya, sehingga Anda dapat mengurangi ruang O(n) menjadi O(1) dengan menggunakan dua variabel. Gunakan prev2 (dua langkah sebelumnya) dan prev1 (satu langkah sebelumnya). Pada setiap langkah, hitung curr dari keduanya, lalu geser nilainya. Ini identik dengan optimisasi Fibonacci menjadi dua variabel.
def num_decodings_o1(s):
if not s or s[0] == '0': return 0
prev2 = 1 # dp[0]
prev1 = 1 # dp[1]
for i in range(2, len(s) + 1):
curr = 0
if s[i-1] != '0':
curr += prev1
two = int(s[i-2:i])
if 10 <= two <= 26:
curr += prev2
prev2, prev1 = prev1, curr
return prev1
print(num_decodings_o1('226')) # 3
print(num_decodings_o1('12')) # 2
print(num_decodings_o1('0')) # 0Menghitung Jalur pada Tangga
Menaiki Tangga (LeetCode 70) menanyakan: ada berapa cara untuk menaiki n anak tangga jika Anda dapat melangkah 1 atau 2 anak tangga setiap kali? Ini persis merupakan barisan Fibonacci: ways(n) = ways(n-1) + ways(n-2). ways(1)=1, ways(2)=2, ways(3)=3, ways(4)=5. Pola ini dapat digeneralisasi jika Anda dapat melangkah hingga k anak tangga: ways(n) = sum(ways(n-1), ..., ways(n-k)).
def climb_stairs(n):
if n <= 2: return n
prev2, prev1 = 1, 2
for _ in range(3, n + 1):
prev2, prev1 = prev1, prev1 + prev2
return prev1
for i in range(1, 8):
print(f'climb_stairs({i}) = {climb_stairs(i)}')
# 1, 2, 3, 5, 8, 13, 21 — Fibonacci!Menaiki Tangga dengan Langkah Bervariasi
Saat Anda dapat mengambil sejumlah langkah dari himpunan tertentu (misalnya, {1, 3, 5}), relasi rekurensinya menjadi dp[i] = sum(dp[i-k] for k in steps if i-k >= 0). Gunakan jendela geser berukuran max(steps) agar penggunaan memori efisien. Ini adalah varian penghitungan masalah ransel tak terbatas — setiap ukuran langkah dapat digunakan berkali-kali.
def count_ways(n, steps):
dp = [0] * (n + 1)
dp[0] = 1 # one way to stay at ground
for i in range(1, n + 1):
for step in steps:
if i >= step:
dp[i] += dp[i - step]
return dp[n]
# Steps of 1 or 2 (classic climbing stairs)
print(count_ways(5, [1, 2])) # 8
# Steps of 1, 3, or 5
print(count_ways(5, [1, 3, 5])) # 5
# Steps of 2 or 3
print(count_ways(6, [2, 3])) # 3 (2+2+2, 3+3, 2+4-invalid, 2+2+2, 3+3, 3+2+1-no...)Biaya Minimum untuk Menaiki Tangga
Biaya Minimum untuk Menaiki Tangga (LeetCode 746) memberikan biaya pada setiap anak tangga dan menanyakan biaya minimum untuk mencapai puncak. Dari anak tangga i, Anda dapat melompat ke i+1 atau i+2. Relasi rekurensinya adalah dp[i] = cost[i] + min(dp[i-1], dp[i-2]). Anda dapat mulai dari anak tangga 0 atau anak tangga 1. Jawabannya adalah min(dp[n-1], dp[n-2]).
def min_cost_climbing(cost):
n = len(cost)
if n == 1: return cost[0]
dp = [0] * n
dp[0] = cost[0]
dp[1] = cost[1]
for i in range(2, n):
dp[i] = cost[i] + min(dp[i-1], dp[i-2])
return min(dp[-1], dp[-2]) # can start from step 0 or 1
print(min_cost_climbing([10, 15, 20])) # 15
print(min_cost_climbing([1, 100, 1, 1, 1, 100, 1, 1, 100, 1])) # 6Cara Mendekode II: Digit Pengganti
Cara Mendekode II (LeetCode 639) memperkenalkan karakter pengganti '*' yang dapat mewakili digit apa pun dari 1 hingga 9. Hal ini meningkatkan jumlah dekode yang valid secara drastis. Satu '*' menyumbang 9 cara (sebagai digit apa pun dari 1 hingga 9). Dua '*' secara bersamaan dapat membentuk 9×9 kombinasi dua digit, tetapi hanya kombinasi yang ≤ 26 yang valid (11-19 = 9 cara, 21-26 = 6 cara → 15 cara untuk '**'). Analisis kasus yang cermat diperlukan.
def num_decodings_ii(s):
MOD = 10**9 + 7
prev2, prev1 = 1, 9 if s[0] == '*' else (0 if s[0] == '0' else 1)
for i in range(1, len(s)):
curr = 0
c, p = s[i], s[i-1]
# Single digit
if c == '*': curr += 9 * prev1
elif c != '0': curr += prev1
# Two digits
if p == '*' and c == '*': curr += 15 * prev2 # 11-19(9) + 21-26(6)
elif p == '*': curr += (2 if c <= '6' else 1) * prev2
elif c == '*': curr += (9 if p == '1' else (6 if p == '2' else 0)) * prev2
else:
two = int(p + c)
if 10 <= two <= 26: curr += prev2
prev2, prev1 = prev1, curr % MOD
return prev1 % MOD
print(num_decodings_ii('*')) # 9
print(num_decodings_ii('1*')) # 18Kaitan dengan Fibonacci
Baik Cara Mendekode maupun Menaiki Tangga merupakan masalah dari keluarga Fibonacci yang disamarkan. Setiap DP yang dp[i]-nya hanya bergantung pada dp[i-1] dan dp[i-2] memiliki bentuk Fibonacci dan dapat diselesaikan dengan ruang O(1). Pemeriksaan validitas (digit nol, ukuran langkah) mengubah transisi mana yang aktif, tetapi tidak mengubah struktur dasar yang melihat dua posisi sebelumnya. Mengenali keluarga ini secara langsung merupakan pola berharga untuk bekerja cepat dalam wawancara.
# Fibonacci family: dp[i] = f(dp[i-1], dp[i-2])
# Fibonacci itself: dp[i] = dp[i-1] + dp[i-2]
# Climbing stairs: dp[i] = dp[i-1] + dp[i-2]
# Decode ways: dp[i] = (dp[i-1] if one_valid) + (dp[i-2] if two_valid)
# Min cost stairs: dp[i] = cost[i] + min(dp[i-1], dp[i-2])
# House robber: dp[i] = max(dp[i-1], nums[i] + dp[i-2])
# All solved with 2 rolling variables:
prev2, prev1 = 0, 1
for _ in range(10):
prev2, prev1 = prev1, prev1 + prev2
print('Fibonacci F(10):', prev1) # 89Menghitung Jalur pada Kisi
Masalah penghitungan terkait: diberikan kisi berukuran m×n, ada berapa jalur unik dari kiri atas ke kanan bawah jika Anda hanya dapat bergerak ke kanan atau ke bawah? Jawabannya adalah koefisien binomial C(m+n-2, m-1). Solusi DP mengisi tabel 2D dengan dp[i][j] = dp[i-1][j] + dp[i][j-1]. Ini merupakan versi 2D dari tangga Fibonacci — setiap sel adalah jumlah sel di atas dan di sebelah kirinya.
def unique_paths(m, n):
dp = [[1] * n for _ in range(m)]
for i in range(1, m):
for j in range(1, n):
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[m-1][n-1]
# Or use math for O(1) solution
import math
def unique_paths_math(m, n):
return math.comb(m + n - 2, m - 1)
print(unique_paths(3, 7)) # 28
print(unique_paths_math(3, 7)) # 28
print(unique_paths(3, 3)) # 6Rangkuman Jebakan Wawancara
Kesalahan umum dalam Cara Mendekode: (1) Lupa bahwa '0' saja tidak valid — selalu periksa s[i-1] != '0' sebelum menambahkan dp[i-1]. (2) Menggunakan two_digit <= 26 tanpa memeriksa two_digit >= 10 — '07' tidak boleh didekode sebagai 'G'. (3) Mengembalikan dp[n-1], bukan dp[n] — tabel menggunakan indeks mulai dari 1 sehingga dp[n] sesuai dengan seluruh untaian. Selalu periksa kembali indeks larik saat tabel DP Anda memiliki satu elemen lebih banyak daripada masukan.
# Common bug: checking two_digit <= 26 without >= 10
def buggy_decode(s):
dp = [0] * (len(s) + 1)
dp[0] = dp[1] = 1
for i in range(2, len(s) + 1):
if s[i-1] != '0': dp[i] += dp[i-1]
two = int(s[i-2:i])
# BUG: '07' gives two=7, and 7 <= 26 would add dp[i-2]
# Fix: require two >= 10
if 10 <= two <= 26: dp[i] += dp[i-2] # CORRECT
return dp[len(s)]
print(buggy_decode('06')) # 0 (correct, '0' alone invalid)
print(buggy_decode('07')) # 0 (correct, '07' not valid, '0' alone invalid)
print(buggy_decode('27')) # 1 (only 'BG', 27>26 so no two-digit)Pemeriksaan Singkat
Uji pemahaman Anda tentang konsep Struktur Data & Algoritma — Persiapan Wawancara Pemrograman dari pelajaran ini.
Rangkuman Pelajaran
Dalam pelajaran ini Anda mempelajari: Cara Mendekode mengikuti relasi rekurensi yang mirip Fibonacci dengan pemeriksaan validitas untuk dekode satu digit (bukan nol) dan dua digit (10-26), Menaiki Tangga dan Tangga Berbiaya Minimum merupakan varian Fibonacci murni yang dapat diselesaikan dengan ruang O(1), dan mengenali keluarga Fibonacci yang melihat dua posisi sebelumnya dapat menghemat banyak waktu saat wawancara. Selanjutnya, kita akan mempelajari DP 2D dengan Jalur Unik dan Jumlah Jalur Minimum pada kisi.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Decode Ways dan Penghitungan Jalur” gratis?
Ya — teks lengkap “Decode Ways dan Penghitungan Jalur” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus DSA Interview Prep, upgrade ke CoddyKit PRO. Kursus DSA Interview Prep mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Decode Ways dan Penghitungan Jalur”?
Selesaikan decode-ways (pemetaan digit ke huruf) sebagai DP mirip Fibonacci, lalu hitung jalur pada tangga dengan ukuran langkah variabel. Kamu berlatih DSA Interview Prep dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai DSA Interview Prep?
Tidak diperlukan pengalaman sebelumnya. DSA Interview Prep di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Decode Ways dan Penghitungan Jalur” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran DSA Interview Prep ini?
Ya. Setiap pelajaran DSA Interview Prep menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- House Robber: Rekurensi Ambil atau Lewati
- Subarray Maksimum dan Subarray Produk Maksimum
- Word Break dan Segmentasi String
- Decode Ways dan Penghitungan Jalur