# **Leetcode筆記(Decode Ways)** :::info :information_source: 題目 : Decode Ways, 類型 : dynamic programming , 等級 : medium 日期 : 2023/04/23,2023/06/13,2023/07/18,2024/09/30 ::: ### 嘗試 ```python class Solution: def numDecodings(self, s: str) -> int: res = 0 def valid_number(num, j): if num == 0 and j != len(s) - 1: res = 0 return if 1 <= num and num <= 26 and j == len(s): res += 1 return for i in range(len(s)): valid_number(int(s[i]), i) for i in range(0, len(s), 2): valid_number(int(s[i]), i) return res ``` 2023/06/13 dp[i]代表 解析s[:i] (從起頭到目前的i為止) 字符串所有可能的組成方式數目 ```python dp[i] = dp[i-1] if s[i] != '0' + dp[i-2] if '9' < s[i-2:i] < '27' ``` ```python class Solution: def numDecodings(self, s: str) -> int: dp = [0] * (len(s) + 1) dp[0] = 1 for i in range(1, len(dp)): if 0 < int(s[i - 1]) < 10: dp[i] = dp[i - 1] if i >= 2 and 10 <= int(s[i - 2 : i]) <= 26: dp[i] += dp[i - 2] return dp[len(s)] ``` 2023/07/18 **如果可以單個存在,就把上一項加起來,如果可以雙個存在,就把前前一項加起來** ```python class Solution: def numDecodings(self, s: str) -> int: # 想法 : 如果可以單個存在 就把上一項加起來 # 如果可以雙個存在 就把前前一項加起來 dp = [0] * (len(s) + 1) dp[0] = 1 for i in range(1, len(s) + 1): if 0 < int(s[i - 1]) < 10: dp[i] = dp[i] + dp[i - 1] if i >= 2 and 10 <= int(s[i - 2] + s[i - 1]) <= 26: dp[i] = dp[i] + dp[i - 2] return dp[len(s)] ``` 2024/09/30 ``` class Solution: def numDecodings(self, s: str) -> int: dp = [0] * (len(s) + 1) dp[0] = 1 for i, c in enumerate(s): n = int(c) if 0 < n <= 9: dp[i + 1] = dp[i] if i > 0: pre_n = int(s[i - 1]) if 10 <= (pre_n * 10 + n) <= 26: dp[i + 1] += dp[i - 1] return dp[-1] ``` --- ### **優化** 对于”226”: 令dp数组为[0,0,0,0],初始化为[1,0,0,0]; 从第一个位置开始,输入为”2”,不为”0”,所以dp数组为[1,1,0,0]; 第2个位置,输入为”2”,不为”0”,所以dp数组为[1,1,1,0];此时前两位数字是”22”,满足区间,所以变为[1,1,2,0]; 第3个位置,输入为”6”,不为”0”,所以dp数组为[1,1,2,2],2為直接延續前面的數字;此时前两位数字是”26”,满足区间,所以再加一種可能变为[1,1,2,3]。 對於"2326" 令dp数组为[0,0,0,0,0],初始化为[1,0,0,0,0]; 从第一个位置开始,输入为”2”,不为”0”,所以dp数组为[1,1,0,0,0]; 第2个位置,输入为”3”,不为”0”,所以dp数组为[1,1,1,0,0];此时前两位数字是”23”,满足区间,所以变为[1,1,2,0,0]; 第3个位置,输入为”2”,不为”0”,所以dp数组为[1,1,2,2,0],2為直接延續前面的數字; 第4个位置,输入为”6”,不为”0”,所以dp数组为[1,1,2,2,2];此时前两位数字是”26”,满足区间,所以变为[1,1,2,2,4],跨一行添加前面的2進來; 时间复杂度为O(n),空间复杂度也为O(n) ```python class Solution: def numDecodings(self, s: str) -> int: # 需要多創一個 並把它初始設定為1 dp = [0] * (len(s) + 1) dp[0] = 1 # 第零格 for i in range(1, len(dp)): # 從第一格開始 # 考慮一位數1-9 (0只能在十位數的後面項) # 事實上是考慮第0個數字(s[0]) 放到第一格dp[1] if int(s[i - 1]) != 0: # 把後面的數移到前面 dp[i] = dp[i - 1] # 考慮兩位數10-26 # s[i - 2 : i]為上一位加現在這一位 if i != 1 and int(s[i - 2 : i]) >= 10 and int(s[i - 2 : i]) <= 26: dp[i] += dp[i - 2] return dp[-1] ``` --- **:warning: 錯誤語法** :::warning ::: **:thumbsup:學習** :::success ::: **思路** **講解連結** https://blog.csdn.net/fuxuemingzhu/article/details/82120874 https://www.youtube.com/watch?v=To5-jVXXbvI&ab_channel=Peter%E5%88%B7Leetcode Provided by. Peter刷Leetcode ###### tags: `dynamic programming` `medium` `leetcode` `值得再想`