这是之前问题的变种(前3题用回溯法,最后一题用DP)
Leetcode 40:组合总和 II(最详细的解法!!!)
Leetcode 216:组合总和 III(最详细的解法!!!)
Leetcode 377:组合总和 Ⅳ(最详细的解法!!!)
这两道问题很类似~
区别在于:
377 的组合数字之间是有顺序的(对于每个目标,每个数字在不同的顺序中可以重复出现,所以以target的顺序为准来遍历)
518的组合数字是无顺序的(对于每个目标,这个数字在第一次出现和第二次出现是一样的,所以以coins的顺序为准来遍历比较好)
- i 和 j 的遍历顺序不同
LeetCode 518:
class Solution(object):
def change(self, amount, coins):
"""
:type amount: int
:type coins: List[int]
:rtype: int
"""
if not coins and amount == 0:
return 1
elif not coins:
return 0
if amount < min(coins) and amount > 0:
return 0
cnt = [0 for j in range(amount+1)]
cnt[0] = 1
## 用nums的前i个元素,加出j有多少种方法
## 得到的nums组合无顺序关系
for i in range(1,len(coins)+1):
for j in range(coins[i-1],amount+1):
cnt[j] += cnt[j-coins[i-1]]
return cnt[-1]
LeetCode 377:
class Solution(object):
def combinationSum4(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if not nums or target == 0:
return 0
cnt = [0 for j in range(target+1)]
cnt[0] = 1
## 全部的nums[0~i]中加出j,有多少种方法。
## 即对于nums的出现是有顺序关系的
for j in range(1,target+1):
for i in range(1,len(nums)+1):
if j >= nums[i-1]:
cnt[j] += cnt[j-nums[i-1]]
return cnt[-1]