Decode Ways medium
Problem Statement
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1 'B' -> 2 ... 'Z' -> 26
Given a non-empty string containing only digits, determine the total number of ways to decode it.
The test cases are generated such that the answer fits in the range [1, 105].
Example 1:
Input: s = "12" Output: 2 Explanation: It could be decoded as "AB" (1 2) or "L" (12).
Example 2:
Input: s = "226" Output: 3 Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
Steps
-
Base Cases: If the string is empty or starts with '0', there are no valid decodings. If the string has length 1, there's only one decoding.
-
Dynamic Programming: We use dynamic programming to build up a solution. Create a DP array
dp
wheredp[i]
represents the number of ways to decode the substrings[0...i]
. -
Iteration: Iterate through the string. For each position
i
:- If
s[i]
is not '0', we can add the number of ways to decode the substring up toi-1
(dp[i-1]
). This represents decoding the current digit individually. - If
s[i-1]
ands[i]
form a number between 10 and 26 (inclusive), we can add the number of ways to decode the substring up toi-2
(dp[i-2]
). This represents decoding the last two digits as a single letter.
- If
-
Result: The final result is
dp[n-1]
, wheren
is the length of the string.
Explanation
The dynamic programming approach avoids redundant calculations. Instead of recursively exploring all possibilities, we build up the solution iteratively. Each dp[i]
depends only on dp[i-1]
and dp[i-2]
, ensuring efficiency.
Code
function numDecodings(s: string): number {
const n = s.length;
if (n === 0 || s[0] === '0') return 0; // Base case: empty or starts with '0'
const dp: number[] = new Array(n + 1).fill(0);
dp[0] = 1; // Empty substring has one way to decode
dp[1] = 1; // Single digit has one way to decode
for (let i = 2; i <= n; i++) {
const currentDigit = parseInt(s[i - 1]);
const twoDigitNum = parseInt(s.substring(i - 2, i));
if (currentDigit >= 1) {
dp[i] += dp[i - 1];
}
if (twoDigitNum >= 10 && twoDigitNum <= 26) {
dp[i] += dp[i - 2];
}
}
return dp[n];
}
Complexity
- Time Complexity: O(n), where n is the length of the string. We iterate through the string once.
- Space Complexity: O(n), due to the
dp
array. This could be optimized to O(1) by only storing the last two DP values.