[
dp
string
]
Leetcode 0091. Decode Ways
Problem statement
https://leetcode.com/problems/decode-ways
Solution 1
Let us use dynamic programming for this problem, where we keep 3
values on each step:
dp[0]
is total numbers to decode numbers[:i]
.dp[1]
is number of ways to decode numbers[:i]
, if it ends with1
and last digit is part of 2-digit number. This is important point.dp[2]
is number of ways to decode numbers[:i]
, if it ends with2
and last digit is part of 2-digit number.
Now, we need to understand how to update our numbers:
- For
dp_new[0]
we can have3
options: if last digit is more than0
, than we can take it as1-digit number
(by definition each part is number between 1 and 26). Also, we can take last number as 2-digit number if it starts with1
: this is exactlydp[1]
. and if it starts with2
and last digit is less or equal to6
. - For
dp_new[1]
we have only one option: we need to have last symbol equal to1
. - Similar for
dp_new[2]
, we need to have last symbol equal to2
.
Complexity: time complexity is O(n)
: we iterate over each symbol once. Space complexity is O(1)
.
class Solution:
def numDecodings(self, s):
dp = [1, 0, 0]
for c in s:
dp_new = [0,0,0]
dp_new[0] = (c > '0') * dp[0] + dp[1] + (c <= '6') * dp[2]
dp_new[1] = (c == '1') * dp[0]
dp_new[2] = (c == '2') * dp[0]
dp = dp_new
return dp[0]
Solution 2
In this problem we can see some repeating subproblems, so we can apply dynamic programming.
Let dp(i)
is number of ways to decode string s[:i]
. Then we can have the following cases:
if i == -1
, we return1
, because there is unique way to decode empty string.- If last digit is not equal to
0
, we need to adddp(i-1)
to our answer. - If last two digits form number from
10
to26
, we can use last2
symbols for decoding, so we adddp(i-2)
to our answer.
Complexity
Time complexity is O(n)
, we have n
states and at most 2
transactions from one to another. Space complexity is O(n)
as well.
Code
class Solution:
def numDecodings(self, s):
@lru_cache(None)
def dp(i):
if i == -1: return 1
ans = 0
if s[i] > "0": ans += dp(i-1)
if i >= 1 and "10" <= s[i-1:i+1] <= "26":
ans += dp(i-2)
return ans
return dp(len(s) - 1)
Remark
If you like the solution, you can upvote it on leetcode discussion section: Problem 0091 Problem 0091