算法# 学习目标:动态规划算法(三 )
学习内容:
动态规划算法:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
在查找有很多重叠子问题的情况的最优解有效。动态规划保存子问题的解,避免重复计算。
学习产出:
分割类题型
动态规划
解决动态规划问题的关键是找到状态转移方程,这样就可以通过计算和存储子问题的解来解决最终问题。
LeetCode 279 完全平方数
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
示例 1:
输入:n = 12
输出:3
解释:12 = 4 + 4 + 4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/perfect-squares
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
状态转移方程不依赖于相邻位置,而是依赖于满足分割条件位置。定义一个以为矩阵dp[i],其中i表示数字,dp[i]表示数字i最少可以由几个完全平方的数相加构成。因此状态转移方程dp[i]=1+min(dp[i-1],dp[i-4],…)
代码(python)
class Solution:
def numSquares(self, n: int) -> int:
dp = [0]*(n+1)
for i in range(1,n+1):
dp[i] =i
j=1
while i-j*j>=0:
dp[i] = min(dp[i],dp[i-j*j]+1)
j+=1
return dp[n]
LeetCode 91 解码方法
一条包含字母 A-Z 的消息通过以下映射进行了 编码 :
‘A’ -> 1
‘B’ -> 2
…
‘Z’ -> 26
要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“111” 可以将 “1” 中的每个 “1” 映射为 “A” ,从而得到 “AAA” ,或者可以将 “11” 和 “1”(分别为 “K” 和 “A” )映射为 “KA” 。注意,“06” 不能映射为 “F” ,因为 “6” 和 “06” 不同。
给你一个只含数字的 非空 字符串 num ,请计算并返回 解码 方法的 总数 。
题目数据保证答案肯定是一个 32 位 的整数。
示例 1:
输入:s = "12"
输出:2
解释:它可以解码为 "AB"(1 2)或者 "L"(12)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/decode-ways
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
dp[i]表示以i为结尾的可能编码数,两种可能,一种是本身作为一个编码,如果符合条件那么dp[i] = dp[i - 1],另外一种是前一个数字和本身构成编码,如果符合条件那么dp[i] = dp[i - 2],这里如果i-2越界了那么就是dp[i] = 1
代码(python)
class Solution:
def numDecodings(self, s: str) -> int:
length = len(s)
dp = [0] * length
dp[0] = 0 if s[0] == '0' else 1
for i in range(1, length):
if s[i] != '0':
t1 = dp[i - 1]
else:
t1 = 0
if i - 2 >= 0:
t2 = dp[i - 2]
else:
t2 = 0
if int(s[i - 1: i + 1]) <= 26 and s[i - 1: i + 1][0] != '0':
t3 = True
else:
t3 = False
if t3:
dp[i] = t1 +t2
else:
dp[i] = t1
if i - 2 < 0 and t3:
dp[i] += 1
return dp[-1]
LeetCode 139 单词拆分
给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-break
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
与完全平方数分割类似,考虑每个分割位置时需要遍历字符串集合,以确定当前位置是否可以成功分割
代码(python)
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
length = len(s)
a = s
dp = [False]*(length+1)
dp[0] = True
for i in range(1,length+1):
for word in wordDict:
wordlength = len(word)
if i >= wordlength and s[i-wordlength:i] == word:
dp[i] = dp[i] or dp[i-wordlength]
return dp[length]