- Define precisely what one DP state represents.
- Establish the base cases before transitions are evaluated.
- Process states in dependency order and combine only already-known values.
Code notes
- 145 lines of Python from the credited upstream file count-good-integers-on-a-grid-path.py.
- The implementation visibly relies on cached states.
- No explicit loop blocks detected.
Complexity
Multiply the number of reachable states by the work performed for each transition, then include the stored state table in memory usage.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
123 45class Solution(object):6 def countGoodIntegersOnPath(self, l, r, directions):7 """8 :type l: int9 :type r: int10 :type directions: str11 :rtype: int12 """13 L = 1614 def count(n):15 digits = [0]*L16 for i in reversed(xrange(len(digits))):17 digits[i] = n%1018 n = 1019 dp = [[0]*10 for _ in xrange(2)]20 dp[1][0] = 121 for i in xrange(L):22 new_dp = [[0]*10 for _ in xrange(2)]23 for t in xrange(2):24 bound = digits[i] if t else 925 for k in xrange(10):26 if not dp[t][k]:27 continue28 for d in xrange(bound+1):29 nk = k30 if lookup[i]:31 if d < k:32 continue33 nk = d 34 new_dp[t and d == bound][nk] += dp[t][k]35 dp = new_dp36 return sum(sum(row) for row in dp)37 38 i = j = 039 lookup = [False]*L40 lookup[i*4+j] = True41 for x in directions:42 if x == 'D':43 i += 144 else:45 j += 146 lookup[i*4+j] = True47 return count(r)-count(l-1)48 49 50515253class Solution2(object):54 def countGoodIntegersOnPath(self, l, r, directions):55 """56 :type l: int57 :type r: int58 :type directions: str59 :rtype: int60 """61 L = 1662 def count(n):63 def memoization(i, t, k):64 if i == L:65 return 166 if not t and memo[i][k] != -1:67 return memo[i][k]68 result = 069 bound = digits[i] if t else 970 for d in xrange(bound+1):71 nk = k72 if lookup[i]:73 if d < k:74 continue75 nk = d 76 result += memoization(i+1, t and d == bound, nk)77 if not t:78 memo[i][k] = result79 return result80 81 digits = [0]*L82 for i in reversed(xrange(len(digits))):83 digits[i] = n%1084 n = 1085 memo = [[-1]*10 for _ in xrange(L)]86 return memoization(0, True, 0)87 88 i = j = 089 lookup = [False]*L90 lookup[i*4+j] = True91 for x in directions:92 if x == 'D':93 i += 194 else:95 j += 196 lookup[i*4+j] = True97 return count(r)-count(l-1)98 99 100101102103class Solution3(object):104 def countGoodIntegersOnPath(self, l, r, directions):105 """106 :type l: int107 :type r: int108 :type directions: str109 :rtype: int110 """111 L = 16112 def count(n):113 def memoization(i, t, k):114 if i == L:115 return 1116 if memo[i][t][k] == -1:117 memo[i][t][k] = 0118 bound = digits[i] if t else 9119 for d in xrange(bound+1):120 nk = k121 if lookup[i]:122 if d < k:123 continue124 nk = d 125 memo[i][t][k] += memoization(i+1, t and d == bound, nk)126 return memo[i][t][k]127 128 digits = [0]*L129 for i in reversed(xrange(len(digits))):130 digits[i] = n%10131 n = 10132 memo = [[[-1]*10 for _ in xrange(2)] for _ in xrange(L)]133 return memoization(0, True, 0)134 135 i = j = 0136 lookup = [False]*L137 lookup[i*4+j] = True138 for x in directions:139 if x == 'D':140 i += 1141 else:142 j += 1143 lookup[i*4+j] = True144 return count(r)-count(l-1)145