##1. 題目內容 ##
一條包含字母 A-Z 的消息通過以下方式進行了編碼:
'A' -> 1
'B' -> 2
...
'Z' -> 26
給定一個只包含數字的非空字符串,請計算解碼方法的總數。
示例 1:
輸入: "12"
輸出: 2
解釋: 它可以解碼爲 "AB"(1 2)或者 "L"(12)。
示例 2:
輸入: "226"
輸出: 3
解釋: 它可以解碼爲 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/decode-ways
著作權歸領釦網絡所有
##2. 基本思路 ##
因爲是按照動態規劃的題目分類做的,所以從一開始就按照動態規劃的模式去思考的。嘗試了幾個實例時候發現類似斐波那契數列,而且似乎只要一維的dp[]數組即可,本來覺得還算簡單,但是沒想到被其中無窮無盡的0搞昏了頭腦。最終還是參考了高贊題解。
按照滑動窗口的思路進行分析,窗口長度爲2,對s進行遍歷,窗口中兩個數字記爲, 。現在按照, 是否爲0,以及是否大於26進行分析:
1. 且 :一旦字符串中出現連續兩個0,將會出現無法解碼的情況,因此直接
return 0
即可;
2. 且 :此時,考慮這個數,只能和前綴組成一種情況,因此此時;且 : 此時要分兩種情況:
3. 若大於26(即爲30 40 50…),也會出現無法解碼的情況,此時return 0
;
4. 若小於26(即爲10或20),這裏相當於只有一種情況,不會對總的解碼次數產生影響,因此;且 :也需要分兩種情況討論:
5. 若小於26,則相當於斐波那契數列,直接即可;
6. 若大於26,相當於只能分開解碼,也對整體解碼次數沒有影響,因此。
3. 代碼實現
class Solution:
def numDecodings(self, s: str) -> int:
l = len(s)
if '00' in s or l == 0 or s[0] == '0':
return 0
elif l == 1:
return l
dp = [0] * l
s_num = s[0] + s[1]
dp[0] = 1
if s[1] == '0' and int(s_num) > 26:
return 0
if int(s_num) > 26 or s[1] == '0':
dp[1] = 1
else:
dp[1] = 2
for i in range(2, l):
s_double = int(s[i-1] + s[i])
if s[i-1] == '0' or (s[i] == '0' and int(s_double) <= 26):
dp[i] = dp[i-2]
elif s[i] == '0' and int(s_double) > 26:
return 0
elif s_double > 26:
dp[i] = dp[i-1]
else:
dp[i] = dp[i-1] + dp[i-2]
return dp[-1]
if __name__ == '__main__':
a = Solution()
b = a.numDecodings('701')
# print(b)
代碼寫的比較醜,湊合看吧~
4. 小結
本來以爲本題的坑在26這邊,避開就好了,殊不知0纔是最大的坑,提交錯誤了八次,好不容易把提交的正確率拉回40%,又白瞎了,心痛。