Decode Ways

Leetcode 91

This is a 1-d DP. Set dp[i]dp[i] to be the decode ways for s[:i+1], we have:

dp[i]=dp[i2]Mi1+dp[i1]Mi2 dp[i] = dp[i-2] \cdot M^{1}_{i} + dp[i-1] \cdot M^{2}_{i}

In which,

Mi1={S[i]A1}Mi2={S[i1:i+1]A2} \begin{aligned} M^{1}_{i} &= | \lbrace S[i] \in A^{1} \rbrace | \\ M^{2}_{i} &= | \lbrace S[i-1:i+1] \in A^{2} \rbrace \end{aligned}

  • Mi1M^{1}_{i} means how many ways to match the 1-character decoders A1A^1 with S[i]S[i]. In this problem we have either 1(S[i]A1S[i] \in A^{1}) or 0(not match, or not exists)
  • Mi2M^{2}_{i} means how many ways to match the 2-character decoders A2A^2 with S[i1:i+1]S[i-1:i+1]. In this problem we have either 1(S[i]A1S[i] \in A^{1}) or 0(not match, or not exists)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution:
    def numDecodings(self, s: str) -> int:
        one = {str(k):1 for k in range(1, 10)}
        two = {str(k):1 for k in range(10, 27)}

        dp = [0]*len(s)
        for i in range(len(s)):
            match_one = one.get(s[i], 0)
            match_two = two.get(s[i-1:i+1], 0) if i-1>=0 else 0
            
            one_bit = dp[i-1]*match_one if i-1>=0 else match_one
            two_bit = dp[i-2]*match_two if i-2>=0 else match_two

            dp[i] = one_bit + two_bit
        
        return dp[-1]

Notes

  1. Use get() to take care of cases when s[i] is not in one
  2. Take care of the corner cases when i<=2i <= 2, in which we can’t get dp values.
  3. Follow Up: Decode Ways 2