322. 零钱兑换
本题是求最小的组合情况,所以递推公式取较小值:dp[j] = min(dp[j], dp[j-coin]+1);
1、确定dp含义
dp在这里表示背包容量能填满的时候所需要硬币数量的最小值。
2、确定递推公式
dp[j] = min(dp[j], dp[j-coin]+1)。
3、确定初始化
dp[0]表示在目标值为0的时候组合数的个数,其余的dp值取为inf,因为需要取最小值。
4、确定遍历顺序
由于是取最小的方法数,所以排列或者组合其实都无所谓。
class Solution(object):
def coinChange(self, coins, amount):
"""
:type coins: List[int]
:type amount: int
:rtype: int
"""
dp = [float('inf')] * (amount+1) # 初始化为最大值,因为后面是求最小值的递推
dp[0] = 0 # 目标为0的时候没有可行方法(因为没有0的coin)
for coin in coins:
for j in range(coin, amount+1): # 正序遍历 or 后续遍历都可以(因为只看最小的元素数)
dp[j] = min(dp[j], dp[j-coin]+1)
return -1 if dp[-1] == float('inf') else dp[-1] # 注意比较后输出
279. 完全平方数
本题是上面一道题的扩展。所不同的是需要进行一步求解满足条件的最大平方数的基底。
class Solution(object):
def numSquares(self, n):
"""
:type n: int
:rtype: int
"""
dp = [float('inf')] * (n+1)
dp[0] = 0
Num = int(sqrt(n)) + 1 # 先计算出符合条件的最大完全平方数的基底
for num in range(1, Num+1): # 从1开始
for j in range(num ** 2, n+1):
dp[j] = min(dp[j], dp[j-num ** 2]+1)
return dp[-1]
139. 单词拆分
本题是字符串尺度上的背包问题。
1、确定dp数组含义
dp[j]表示在给定字符串j位置是否可以由字典中的元素构成。是一个bool类型。
2、确定确定递推公式
在两个条件都满足的情况下才可以判断当前为true:
(1)在加入长度为j-i的字符串前dp[j]已经是true;
(2)目标字符串s[i-j]这个子串是在字典里的。
3、确定初始化
由于递推公式是吧满足条件的设置为true,所以初始化为false。又因为需要dp[0]来进行and操作的递推,所以dp[0]=true(本身没有含义,仅占位)。
4、确定遍历顺序
和组合数凑够目标和不一样,本题字符串需要保证顺序也一致,所以需要确定为组合数:先便利背包,再遍历物品(保证每个背包容量都能遍历一遍物品,才能达到排列的效果)。
class Solution(object):
def wordBreak(self, s, wordDict):
"""
:type s: str
:type wordDict: List[str]
:rtype: bool
"""
dp = [False] * (len(s)+1)
dp[0] = True
for i in range(1, len(s)+1):
for j in range(i):
if dp[j] == True and s[j:i] in wordDict:
dp[i] = True
return dp[-1]
Day44完结!!!