Decode Ways II⚓︎
Description⚓︎
A message containing letters from A-Z
can be encoded into numbers using the following mapping:
To decode an encoded message, all the digits must be grouped then mapped back into letters using the reverse of the mapping above (there may be multiple ways). For example, "11106"
can be mapped into:
"AAJF"
with the grouping(1 1 10 6)
"KJF"
with the grouping(11 10 6)
Note that the grouping (1 11 06)
is invalid because "06"
cannot be mapped into 'F'
since "6"
is different from "06"
.
In addition to the mapping above, an encoded message may contain the '*'
character, which can represent any digit from '1'
to '9'
('0'
is excluded). For example, the encoded message "1*"
may represent any of the encoded messages "11"
, "12"
, "13"
, "14"
, "15"
, "16"
, "17"
, "18"
, or "19"
. Decoding "1*"
is equivalent to decoding any of the encoded messages it can represent.
Given a string s
consisting of digits and '*'
characters, return the number of ways to decode it.
Since the answer may be very large, return it modulo 10^9 + 7
.
Example 1:
- Input:
s = "*"
- Output:
9
- Explanation:
Example 2:
- Input:
s = "1*"
- Output:
18
- Explanation:
Example 3:
- Input:
s = "2*"
- Output:
15
- Explanation:
Constraints:
1 <= s.length <= 10^5
s[i]
is a digit or'*'
.
Solution⚓︎
Top-Down⚓︎
Bottom-Up⚓︎
Initial Setup:
- DP Array Initialization:
dp[n] = 1;
This base case facilitates the computation ofdp[i]
fori < n
by providing a starting point indicating that there is exactly one way to decode an empty string.
Single-Character Decoding:
When decoding a single character, there are two cases to consider:
- The character is a digit (
1
-9
): Each of these characters can only be decoded in one way (e.g.,'1' -> 'A'
,'2' -> 'B'
, etc.). - The character is a wildcard (
*
): The'*'
can represent any digit from'1'
to'9'
, so there are9
ways to decode it.
The code dp[i] = dp[i + 1] * (s[i] == '*' ? 9 : 1);
calculates the number of ways to decode the string starting from position i
considering only the single-character decoding at position i
. It multiplies the number of ways to decode the substring starting from i+1
by 9
if the current character is '*'
, or by 1
if it's any digit from 1
to 9
.
Two-Character Decoding:
This is where the solution gets more nuanced, as it has to account for combinations of digits and '*'
, and how they can form valid two-digit numbers (10
to 26
).
-
Both characters are digits: The solution converts the two characters to an integer and checks if it's within the range
10
to26
. If so, this adds to the number of waysdp[i+2]
can decode the rest of the string starting from positioni+2
. -
The first character is a digit and the second is
'*'
: - If the first character is
'1'
, the'*'
can represent any digit from'1'
to'9'
, thus forming the numbers11
to19
. Each of these is a valid encoding, so we add9 * dp[i+2]
. -
If the first character is
'2'
, the'*'
can represent digits from'1'
to'6'
(forming the numbers21
to26
), contributing6 * dp[i+2]
ways. -
The first character is
'*'
and the second is a digit: - If the second digit is between
'1'
and'6'
, the first'*'
can be'1'
or'2'
, doubling the possibilities (2 * dp[i+2]
). -
If the second digit is between
'7'
and'9'
, the'*'
can only represent'1'
to match the encoding rules, resulting indp[i+2]
. -
Both characters are
'*'
: This represents the most combinations, as'*'
can be'1'
or'2'
forming valid two-digit numbers11
to19
and21
to26
. There are9
possibilities for the first'*'
, and for the second'*'
, there are6
possibilities when the first'*'
is'2'
. Therefore, there are9 + 6 = 15
total ways, resulting in15 * dp[i+2]
.
Space-optimized approach: