322.零钱兑换
(一)我的思想:
(1)明确 dp 数组的含义,dp[n] 表示装满容量 n 所需要的最少零钱数
(2)确定递归公式 dp [j] = min( dp [ j - coins [ i ] ], dp [ j ] )
(3)初始化 dp 数组,dp [0] = 0,其余 dp [j] 初始值都是一个最大数(在这里我取amount+1为最大值,因为题目中要求amount最大值为10000),这样进行 min 操作时才不会被覆盖更小的值
(4)确定遍历顺序,先遍历背包再遍历物品求排列数,先遍历物品再遍历背包求组合数
代码实现如下:
class Solution(object):
def coinChange(self, coins, amount):
"""
:type coins: List[int]
:type amount: int
:rtype: int
"""
dp = []
dp.append(0)
for i in range(1,amount+1):
dp.append(float('inf'))
if amount==0:
return 0
for coin in coins:
for j in range(coin,amount+1):
dp[j] = min(dp[j-coin]+1,dp[j])
if dp[amount]==float('inf'):
return -1
return dp[amount]
139.单词拆分
(一)我的思想:按照想当然的思路,不断查找字典中是否存在构成字符串 s 的部分,有的话则缩短原来的字符串 s ,最后通过判断字符串是否被缩短为空来判断字符串 s 是否能由字典中元素构成,乍一看好像挺合理,但实际运行时漏洞百出,比如例子字符串 s =cars,字典元素car,ca,rs,按照我的思路第一轮循环缩短字符后肯定无法正确判断了,输出false,但理论上应该由后面ca和rs拼出cars。
class Solution(object):
def wordBreak(self, s, wordDict):
"""
:type s: str
:type wordDict: List[str]
:rtype: bool
"""
for word in wordDict:
if word in s:
print(word,s)
s = s.replace(word,"")
self.wordBreak(s,wordDict)
if s=="":
return True
return False
(二)网上思路:很多题目都可以用装背包思想来理解,比如这道题,可以理解为能否用字典中的元素装满一个容量为字符串 s 的背包,但是定义 dp 数组时是使用字符串长度 i 作为下标,下标永远是一个 int 类型的,而如果我想用一个字符串类型作下标,是正常思路,但代码怎么知道怎么查分出你想的字符串呢,还是要一个字符一个字符的添加,看添加进的一串字符是否出现在字典里。
代码实现如下:
class Solution(object):
def wordBreak(self, s, wordDict):
"""
:type s: str
:type wordDict: List[str]
:rtype: bool
"""
dp = []
for i in range(len(s)+1):
dp.append(False)
dp[0] = True
for i in range(1, len(s)+1):
for j in range(0, i):
if s[j:i] in wordDict and dp[j]:
dp[i] = True
return dp[len(s)]