44. Wildcard Matching
func isMatch(s string, p string) bool {
dp := make([][]bool, len(s)+1) // dp[s_idx][p_idx]
for i := range dp {
dp[i] = make([]bool, len(p)+1)
}
// init dp start from the table initiated as False everywhere but dp[0][0] = True.
dp[0][0] = true
// above miss to compute the situation when s is '' but p is not
for j := 1; j <= len(p); j++ {
if p[j-1] == '*' {
dp[0][j] = dp[0][j-1]
}
}
// apply two rules
// 1. if s[s_idx-1] = p[p_idx-1] dp[i][j] i: idx of s, j: idx of p = dp[i-1][j-1]
// 2. if p[p_idx-1] = '*' and dp[i][j-1] = true or dp[i-1][j-1], dp[idx][j] = true for all idx >= i-1
// case: s = a p = a* dp[1][2] = dp[1][1], s = a p = * dp[1][1] = dp[0][1]
for i := 1; i <= len(s); i++ {
for j := 1; j <= len(p); j++ {
if dp[i][j] == true { // because of 下面的 rule2
continue
}
if s[i-1] == p[j-1] || p[j-1] == '?'{ // rule1
dp[i][j] = dp[i-1][j-1]
}else if p[j-1] == '*' { // rule2
if dp[i][j-1] == true || dp[i-1][j] == true {
for idx := i; idx <= len(s); idx++ {
dp[idx][j] = true
}
}
}
}
}
return dp[len(s)][len(p)]
}
func isMatch(s string, p string) bool {
// mem[i][j] means isMatch(s[:i], p[:j])
mem := make([][]bool, len(s)+1)
for i := range mem {
mem[i] = make([]bool, len(p)+1)
}
// init bound, mem[n][0] is false while n > 0
mem[0][0] = true
for j := 1; j <= len(p); j++ {
if p[j-1] == '*' {
mem[0][j] = mem[0][j-1]
}
}
for i := 1; i <= len(s); i++ {
for j := 1; j <= len(p); j++ {
if p[j-1] == '*' {
// mem[i][j] = mem[i][j-1] 則* 匹配空字符串, =mem[i-1][j]則j匹配任意當前字符串
mem[i][j] = mem[i][j-1] || mem[i-1][j]
} else if p[j-1] == '?' || p[j-1] == s[i-1] {
mem[i][j] = mem[i-1][j-1]
}
}
}
return mem[len(s)][len(p)]
}
410. Split Array Largest Sum
參考
https://leetcode.com/problems/split-array-largest-sum/discuss/89816/DP-Java
func splitArray(nums []int, m int) int {
// dp
length := len(nums)
dp := make([][]int, length+1)
// init dp[][]
for i := 0; i <= length; i++ {
dp[i] = make([]int, m+1)
for j := 0; j <= m; j++ {
dp[i][j] = math.MaxInt32
}
}
preSum := make([]int, length+1)
for i, v := range nums {
preSum[i+1] = preSum[i] + v
}
dp[0][0] = 0
for i:= 1; i <= length; i++ {
for j := 1; j <= m; j++ {
for k := 0; k < i; k++ { // 0 <= k < i
// dp[i][j] nums[0]~nums[i] split to j parts
dp[i][j] = min(dp[i][j], max(dp[k][j-1], preSum[i] - preSum[k]))
}
}
}
return dp[length][m]
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a < b {
return b
}
return a
}
312. Burst Balloons
dp[i][j] in here means, the maximum coins we get after we burst all the balloons between i+1 and j-1 in the array
class Solution(object):
def maxCoins(self, nums):
nums = [1] + nums + [1]
n = len(nums)
dp = [[0] * n for _ in xrange(n)]
print n
for gap in range(2, n):
for left in range(0, n-gap):
right = left + gap
for i in range(left+1, right): # left, right are not included for the last burst, they are the edges
dp[left][right] = max(dp[left][right],
nums[left]*nums[i]*nums[right] + dp[left][i] + dp[i][right])
return dp[0][-1]
1000. Minimum Cost to Merge Stones
https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-1000-minimum-cost-to-merge-stones/
class Solution(object):
def mergeStones(self, stones, K):
n = len(stones)
if (n-1) % (K-1): return -1
inf = float('inf')
preSum = [0] * (n+1)
for i in xrange(n):
preSum[i+1] = stones[i] + preSum[i]
# dp[i][j][k] := min cost to merge subarray i~j into k piles.
dp = [[[inf] * (K+1) for _ in xrange(n)] for _ in xrange(n)]
for i in xrange(n):
dp[i][i][1] = 0
for l in xrange(2, n+1): # subproblem length
for i in xrange(n-l+1):
j = i + l - 1
for k in xrange(2, K+1):
for m in xrange(i, j):
dp[i][j][k] = min(dp[i][j][k], dp[i][m][1] + dp[m+1][j][k-1])
if dp[i][j][K] < inf:
dp[i][j][1] = dp[i][j][K] + preSum[j+1] - preSum[i]
return dp[0][-1][1]
446. Arithmetic Slices II - Subsequence
class Solution(object):
def numberOfArithmeticSlices(self, A):
# dp[i][j] the number of arithmetic ending with idx ith, increment is j
dp = [collections.defaultdict(int) for _ in A]
re = 0
for i in xrange(len(A)):
for j in xrange(i):
dp[i][A[i]-A[j]] += 1 # 把2個的也加入
if A[i]-A[j] in dp[j]:
dp[i][A[i]-A[j]] += dp[j][A[i]-A[j]] # dp[j]是至少兩個的, dp[i]是比dp[j]多一個的, 因爲上面加1了,所以這裏不加1
re += dp[j][A[i]-A[j]] # dp[j][A[i]-A[j]] + 1 - 1
return re
329. Longest Increasing Path in a Matrix
class Solution(object):
def longestIncreasingPath(self, matrix):
def dfs(i, j):
if not dp[i][j]:
val = matrix[i][j]
dp[i][j] = 1 + max(dfs(i-1, j) if i > 0 and matrix[i-1][j] < val else 0, # dfs不是dp
dfs(i+1, j) if i+1 < len(matrix) and matrix[i+1][j] < val else 0,
dfs(i, j-1) if j > 0 and matrix[i][j-1] < val else 0,
dfs(i, j+1) if j+1 < len(matrix[0]) and matrix[i][j+1] < val else 0)
return dp[i][j]
if not matrix or not matrix[0]: return 0
dp = [[0] * len(matrix[0]) for _ in xrange(len(matrix))]
return max(dfs(i, j) for i in xrange(len(matrix)) for j in xrange(len(matrix[0])))
518. Coin Change 2
class Solution(object):
def change(self, amount, coins):
"""
:type amount: int
:type coins: List[int]
:rtype: int
"""
dp = [0] * (amount+1)
dp[0] = 1 # so that dp[amou-coin=0] = 1
for c in coins:
for amou in xrange(1, amount+1):
if amou >= c:
dp[amou] += dp[amou-c]
return dp[amou]
322. Coin Change
class Solution(object):
def coinChange(self, coins, amount):
"""
:type coins: List[int]
:type amount: int
:rtype: int
"""
dp = collections.defaultdict(int)
coins = sorted(coins)
for money in xrange(1, amount+1):
minCoins = 5000
for coin in coins:
if money-coin>=0 and dp[money-coin] != -1:
minCoins = min(dp[money-coin], minCoins)
if minCoins == 5000:
dp[money] = -1
else:
dp[money] = minCoins + 1
return dp[amount]
174. Dungeon Game
第一次解,超時:
class Solution(object):
def dfs(i, j, val, minVal):
val += d[i][j]
if i == len(d) - 1 and j == len(d[0])-1:
return minVal
rightward = float('-inf')
if j + 1 <= len(d[0]) - 1 :
rightward = dfs(i, j+1, val, minVal)
downward = float('-inf')
if i + 1 <= len(d) - 1:
downward = dfs(i+1, j, val, minVal)
return max(rightward, downward)
re = dfs(0, 0, 0, 0)
return -re + 1 if re <= 0 else 1
DP, 自底向上
class Solution(object):
def calculateMinimumHP(self, d):
# hp[i][j] to store the min hp needed at position (i, j)
# adding dummy row and column to hp would make the code cleaner
r, c = len(d), len(d[0])
hp = [[sys.maxint] * (c+1) for _ in xrange(r+1)]
hp[r][c-1] = 1
hp[r-1][c] = 1
for i in xrange(r-1, -1, -1):
for j in xrange(c-1, -1, -1):
need = min(hp[i+1][j], hp[i][j+1]) - d[i][j]
# 這裏負數要設爲1,因爲如左下角10往上走的時候,纔會是1+5+2
hp[i][j] = need if need > 0 else 1
return hp[0][0]
213. House Robber II
dp, 首尾是環,轉換成2部分
- Rob houses
0
ton - 2
; - Rob houses
1
ton - 1
.
class Solution(object):
def rob(self, nums):
if len(nums) == 1:
return nums[0]
def robHouse(nums, low, high):
pre2 = pre1 = 0
cur = 0
for i in xrange(low, high):
cur = max(pre1, pre2+nums[i])
pre2 = pre1
pre1 = cur
return cur
return max(robHouse(nums, 0, len(nums)-1), robHouse(nums, 1, len(nums)))
368. Largest Divisible Subset
LIS算法的變形,原理一樣
class Solution(object):
def largestDivisibleSubset(self, nums):
if not nums:
return []
nums = sorted(nums)
dp = [[nums[0]] for i in nums]
res = [nums[0]]
for i in xrange(1, len(nums)):
dp[i] = [nums[i]]
for j in xrange(0, i):
if nums[i] % nums[j] == 0:
dp[i] = dp[j] + [nums[i]] if len(dp[j]) >= len(dp[i]) else dp[i]
res = dp[i] if len(res) < len(dp[i]) else res
return res
263. Ugly Number
給ugly Number 2做鋪墊
class Solution(object):
def isUgly(self, num):
rest = num
if rest == 0:
return False
while rest != 1:
if rest % 2 == 0:
rest /= 2
elif rest % 3 == 0:
rest /= 3
elif rest % 5 == 0:
rest /= 5
else:
return False
return True
別人的寫法:汗顏,學習了。 num%p == 0 < num 相當於 Num%p == 0 and num%p < num
for p in 2, 3, 5:
while num % p == 0 < num:
num /= p
return num == 1
264. Ugly Number II
Explanation:
The key is to realize each number can be and have to be generated by a former number multiplied by 2, 3 or 5
e.g.
1 2 3 4 5 6 8 9 10 12 15..
what is next?
it must be x * 2 or y * 3 or z * 5, where x, y, z is an existing number.
How do we determine x, y, z then?
apparently, you can just traverse the sequence generated by far from 1 ... 15, until you find such x, y, z that x * 2, y * 3, z * 5 is just bigger than 15. In this case x=8, y=6, z=4. Then you compare x * 2, y * 3, z * 5 so you know next number will be x * 2 = 8 * 2 = 16.
k, now you have 1,2,3,4,....,15, 16,
Then what is next?
You wanna do the same process again to find the new x, y, z, but you realize, wait, do I have to
traverse the sequence generated by far again?
NO! since you know last time, x=8, y=6, z=4 and x=8 was used to generate 16, so this time, you can immediately know the new_x = 9 (the next number after 8 is 9 in the generated sequence), y=6, z=4.
Then you need to compare new_x * 2, y * 3, z * 5. You know next number is 9 * 2 = 18;
And you also know, the next x will be 10 since new_x = 9 was used this time.
But what is next y? apparently, if y=6, 6*3 = 18, which is already generated in this round. So you also need to update next y from 6 to 8.
Based on the idea above, you can actually generated x,y,z from very beginning, and update x, y, z accordingly. It ends up with a O(n) solution.
class Solution(object):
def nthUglyNumber(self, n):
dp = [1]*(n+1)
n2 = n3 = n5 = 1
for i in xrange(2, n+1):
dp[i] = min(dp[n2]*2, dp[n3]*3, dp[n5]*5)
if dp[n2]*2 == dp[i]:
n2 += 1
if dp[n3]*3 == dp[i]:
n3 += 1
if dp[n5]*5 == dp[i]:
n5 += 1
return dp[n]
467. Unique Substrings in Wraparound String
思路:
- The max number of unique substring ends with a letter equals to the length of max contiguous substring ends with that letter. Example
"abcd"
, the max number of unique substring ends with'd'
is 4, apparently they are"abcd", "bcd", "cd" and "d"
. - If there are overlapping, we only need to consider the longest one because it covers all the possible substrings. Example:
"abcdbcd"
, the max number of unique substring ends with'd'
is 4 and all substrings formed by the 2nd"bcd"
part are covered in the 4 substrings already. - No matter how long is a contiguous substring in
p
, it is ins
sinces
has infinite length. - Now we know the max number of unique substrings in
p
ends with'a', 'b', ..., 'z'
and those substrings are all ins
. Summary is the answer, according to the question.
class Solution(object):
def findSubstringInWraproundString(self, p):
dp = [0] * 26
re = 0
pre = 0
for i in xrange(len(p)):
if (ord(p[i]) - ord(p[i-1])) in (1, -25):
cur = pre + 1
else:
cur = 1
pre = cur
val = ord(p[i])-ord('a')
dp[val] = max(dp[val], cur)
return sum(dp)
139. Word Break
思路:
class Solution(object):
def wordBreak(self, s, wordDict):
dp = [False] * len(s)
for i in xrange(0, len(s)):
for w in wordDict:
if i-len(w)+1 >= 0:
if w == s[i-len(w)+1: i+1] and (dp[i-len(w)] or i-len(w) == -1):
dp[i] = True
return dp[-1]
BFS
I use BFS to avoid useless states calculation like someone did in Coin Change. I do not check every substring but I check the substring whose length is possible (I store all distinct length of words in a list). Thus, no need to check backward from the current position one by one.
class Solution(object):
def wordBreak(self, s, wordDict):
"""
:type s: str
:type wordDict: Set[str]
:rtype: bool
"""
queue = [0]
slen = len(s)
lenList = [l for l in set(map(len,wordDict))]
visited = [0 for _ in range(0, slen + 1)]
while queue:
tmpqueue = []
for start in queue:
for l in lenList:
if s[start:start+l] in wordDict:
if start + l == slen:
return True
if visited[start + l] == 0:
tmpqueue.append(start+l)
visited[start + l] = 1
queue, tmpqueue = tmpqueue, []
return False
673. Number of Longest Increasing Subsequence
Given an unsorted array of integers, find the number of longest increasing subsequence.
Example 1:
Input: [1,3,5,4,7]
Output: 2
Explanation: The two longest increasing subsequence are [1, 3, 4, 7] and [1, 3, 5, 7].
Example 2:
Input: [2,2,2,2,2]
Output: 5
Explanation: The length of longest continuous increasing subsequence is 1, and there are 5 subsequences' length is 1, so output 5.
思路:
The idea is to use two arrays len[n]
and cnt[n]
to record the maximum length of Increasing Subsequence and the coresponding number of these sequence which ends with nums[i]
, respectively. That is:
len[i]
: the length of the Longest Increasing Subsequence which ends with nums[i]
.cnt[i]
: the number of the Longest Increasing Subsequence which ends with nums[i]
.
Then, the result is the sum of each cnt[i]
while its corresponding len[i]
is the maximum length.
class Solution(object):
def findNumberOfLIS(self, nums):
if not nums:
return 0
count, dp = [0 for i in nums], [1 for i in nums]
for i in xrange(len(nums)):
for j in xrange(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i], dp[j]+1)
for j in xrange(i):
if nums[j] < nums[i] and dp[i]-1 == dp[j]:
count[i] += count[j] if count[j] else 1
res = 0
for i in xrange(len(nums)):
if dp[i] == max(dp):
res += count[i] if count[i] else 1
return res
576. Out of Boundary Paths
Note:
- Once you move the ball out of boundary, you cannot move it back.
- The length and height of the grid is in range [1,50].
- N is in range [0,50].
- 這道題乍一看很像一個標準的bfs,因爲限定最多隻能移動N次,我們只要bfs依次遍歷發現出界就+1,當bfs的深度大於N的時候break。當然理論上是沒有任何問題的,確實能得出正確答案,但是這裏N的取值範圍達到了50,我們對任意一個點bfs有四個方向(可以走回頭路),那麼複雜度達到了4^N,顯然會超時。當然我會在文章後面給出bfs的做法,畢竟這是可以處理N比較小的情況的解法,讓大家更熟悉bfs的套路。
- 我不知道你們有沒有這種感覺,一般看到這個mod 1e9+7,這道題8成就是dp了,而且就是那種每個dp值你都得mod一下再去進行運算的那種。我覺得這算一個小技巧吧,看到mod 1e9+7就要想到dp。
- 顯然,這裏dp很好定義,我們定義
dp[(i,j,N)]
表示從i,j出發,最多走N步情況下滿足題意的路徑數量
,那麼我們所求也就是dp[(i,j,N)]。根據我們上面說的bfs的思路,遞推式可得:dp[(i,j,N)] = dp[(i+1,j,N-1)] + dp[(i-1,j,N-1)] + dp[(i,j+1,N-1)] + dp[(i,j-1,N-1)]
class Solution(object):
def findPaths(self, m, n, N, i, j):
"""
:type m: int
:type n: int
:type N: int
:type i: int
:type j: int
:rtype: int
"""
mod = 10**9 + 7
cache = collections.defaultdict(int)
def helper(N, i, j, cache):
if (i, j, N) in cache:
return cache[(i, j, N)]
if 0<=i<m and 0<=j<n:
if N == 0:
cache[(i, j, N)] = 0
return 0
for x, y in ((i-1, j), (i+1, j), (i, j-1), (i, j+1)):
cache[(i, j, N)] += helper(N-1, x, y, cache)
return cache[(i, j, N)] % mod
else:
cache[(i, j, N)] = 1
return 1
return helper(N, i, j, cache)
|
|
787. Cheapest Flights Within K Stops
Dijkstra's algorithm 每次更新剩餘點到起始點的價格。
There are n
cities connected by m
flights. Each fight starts from city u
and arrives at v
with a price w
.
Now given all the cities and fights, together with starting city src
and the destination dst
, your task is to find the cheapest price from src
to dst
with up to k
stops. If there is no such route, output -1
.
Example 1: Input: n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] src = 0, dst = 2, k = 1 Output: 200 Explanation: The graph looks like this: The cheapest price from city0
to city2
with at most 1 stop costs 200, as marked red in the picture.
Example 2: Input: n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] src = 0, dst = 2, k = 0 Output: 500 Explanation: The graph looks like this: The cheapest price from city0
to city2
with at most 0 stop costs 500, as marked blue in the picture.
class Solution(object):
def findCheapestPrice(self, n, flights, src, dst, K):
"""
:type n: int
:type flights: List[List[int]]
:type src: int
:type dst: int
:type K: int
:rtype: int
"""
prices = collections.defaultdict(dict)
for a, b, p in flights:
prices[a][b] = p
heap = [(0, src, K+1)]
while heap:
price, curPlace, steps = heapq.heappop(heap)
if curPlace == dst:
return price
if steps > 0:
for arr in prices[curPlace]:
heapq.heappush(heap, (price+prices[curPlace][arr], arr, steps-1))
return -1
304. Range Sum Query 2D - Immutable
Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2).
The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, col2) = (4, 3), which contains sum = 8.
Example:
Given matrix = [
[3, 0, 1, 4, 2],
[5, 6, 3, 2, 1],
[1, 2, 0, 1, 5],
[4, 1, 0, 1, 7],
[1, 0, 3, 0, 5]
]
sumRegion(2, 1, 4, 3) -> 8
sumRegion(1, 1, 2, 2) -> 11
sumRegion(1, 2, 2, 4) -> 12
class NumMatrix(object):
def __init__(self, matrix):
"""
:type matrix: List[List[int]]
"""
dpSum = [[0]*len(matrix[0]) for i in matrix]
for i in xrange(len(matrix)):
for j in xrange(len(matrix[0])):
if j-1>=0:
dpSum[i][j] += dpSum[i][j-1]
for row in xrange(0, i+1):
dpSum[i][j] += matrix[row][j]
self.dpSum = dpSum
def sumRegion(self, row1, col1, row2, col2):
"""
:type row1: int
:type col1: int
:type row2: int
:type col2: int
:rtype: int
"""
res = self.dpSum[row2][col2]
if col1 - 1 >= 0:
res -= self.dpSum[row2][col1-1]
if row1 -1 >= 0:
res -= self.dpSum[row1-1][col2]
if col1 - 1 >= 0 and row1 -1 >= 0:
res += self.dpSum[row1-1][col1-1]
return res
# Your NumMatrix object will be instantiated and called as such:
# obj = NumMatrix(matrix)
# param_1 = obj.sumRegion(row1,col1,row2,col2)
464. Can I Win
遊戲的可以整理一篇,都是暴力破解(遞歸)加記憶。DP用於記錄計算過的路徑避免重複計算。
class Solution(object):
def canIWin(self, maxChoosableInteger, desiredTotal):
choose = tuple(i for i in xrange(1, maxChoosableInteger+1))
visited = {}
if sum(choose) < desiredTotal: return False
def helper(target, choose, visited):
if len(choose) == 0:
return False
if choose in visited: return visited[choose]
if target - max(choose) <= 0:
visited[choose] = True
return True
for n in choose:
leftChoose = tuple(x for x in choose if x!=n)
# 對方輸,我方就贏
if not helper(target-n, leftChoose, visited):
visited[choose] = True
return True
visited[choose] = False
return False
return helper(desiredTotal, choose, visited)
523. Continuous Subarray Sum
思路:
暴力破解就不說了,
在討論裏有個大神給出了時間複雜度是O(nn)的解法,他的思路非常巧妙,用了數學上的知識,下面給出他的解法的原理:
假設:
a[i]+a[i+1]+...+a[j]=n1k+q;a[i]+a[i+1]+...+a[j]=n1k+q;
如果存在一個n
n>j且a[i]+a[i+1]+...+a[j]+...+a[n]=n2k+q;n>j且a[i]+a[i+1]+...+a[j]+...+a[n]=n2k+q;
那麼
a[j+1]+...+a[n]=(n2−n1)ka[j+1]+...+a[n]=(n2−n1)k
因此利用這一結果,可以從序列第一個元素開始遍歷,不斷累加上當前的元素,並求出當前和除以k後的餘數,用一個映射記錄該餘數出現時的下標,如果同一個餘數出現了兩次,並且兩次出現的下標之差大於1,那麼就表示在這兩個座標之間的元素之和是k的倍數,因此就可以返回true,否則最後返回false。
需要注意的兩個地方:
1. k可能取0,所以只有當k不爲0時纔對當前的和求餘,同時針對於nums = [0, 0], k = 0的情況,需要添加一個初始映射(0, -1)來確保結果的正確。
2. 下標之差至少爲2纔算是正確的情況,因爲題目要求子序列長度至少爲2,以上面的例子就是n至少等於j+2。
具體實現見下面參考代碼。
class Solution(object):
def checkSubarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
if len(nums) < 2:
return False
if k == 0:
for i in range(0, len(nums) - 1):
if nums[i] == 0 and nums[i+1] == 0:
return True
return False
k = abs(k)
if len(nums) >= 2*k:
return True
Sum = [0]
for x in nums:
Sum.append((Sum[-1]+x)%k)
Dict = {}
for i in xrange(len(Sum)):
if Dict.has_key(Sum[i]):
if i - Dict[Sum[i]] >= 2:
return True
else:
Dict[Sum[i]] = i
return False
91. Decode Ways
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.
Example 1:
Input: "12"
Output: 2
Explanation: It could be decoded as "AB" (1 2) or "L" (12).
Example 2:
Input: "226"
Output: 3
Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
i指的是字符串長度。
class Solution(object):
def numDecodings(self, s):
"""
:type s: str
:rtype: int
"""
if s[0] == '0':
return 0
dp = [0 for i in xrange(len(s)+1)]
dp[0] = 1
dp[1] = 0 if s[0] == '0' else 1
for i in xrange(2, len(s)+1):
one = int(s[i-1])
two = int(s[i-2:i])
if 1 <= one:
dp[i] = dp[i-1]
if 10 <= two <= 26:
dp[i] += dp[i-2]
return dp[-1]
639. Decode Ways II
等於切出最後一位和最後2位,看1位的幾種和2位的幾種 分別乘以對應的dp[i-1], dp[i-2]
這題的解法上一題也可以用。
** = 11-19, 21-26. 如果** 是比如 37的話,應該是在one裏面
class Solution(object):
def numDecodings(self, s):
one = {'0': 0, '1': 1, '2': 1, '3': 1, '4': 1, '5': 1, '6': 1, '7': 1, '8': 1, '9': 1, '*': 9}
two = {'10': 1, '11': 1, '12': 1, '13': 1, '14': 1, '15': 1, '16': 1, '17': 1, '18': 1, '19': 1, '20': 1, '21': 1,
'22': 1, '23': 1, '24': 1, '25': 1, '26': 1, '*0': 2, '*1': 2, '*2': 2, '*3': 2, '*4': 2, '*5': 2, '*6': 2,
'*7': 1, '*8': 1, '*9': 1, '1*': 9, '2*': 6, '**': 15}
dp = [1, one.get(s[0])] # dp[i-2], dp[i-1]
for i in xrange(1, len(s)):
dp = dp[1], (one.get(s[i]) * dp[1] + two.get(s[i-1: i+1], 0) * dp[0]) % 1000000007
return dp[-1]