刷题顺序如下:
第一题:

python
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
output = []
def dfs(inputs,lists, sums):
if sums == target:
output.append(lists)
return
n = len(inputs)
for i in range(n):
if sums + inputs[i] > target: #枝剪
return
dfs(inputs[i:],lists + [inputs[i]], sums + inputs[i]) #表示可以选自己
dfs(candidates,[],0)
return output
记住以下两个要点:
- for i in range(n)表示的是以inputs中的每一个num为起始,去枚举所有的lists.(可以可以按照第一次调用dfs来理解)
以上面的例子为例:对于进入的第一个dfs循环,相当于依次枚举以1开头的所有满足要求的lists,以2为开头的所有满足要求的lists,以及以3为开头的所有满足要求的list
2.dfs中再调用dfs时,inputs的输入
- 如果可以重复选取,那么inputs为inputs[i:]。
- 如果不能重复选取,那么inputs为inputs[i+1:].
第二题:

1.因为是不能重复选取,所以在dfs中调用dfs时候,inputs为inputs[i+1:].
2.注意有一个枝剪的过程:
以上面的例子来说面,排序后candidates = [1,1,2,5,6,7,10]。按照我们上面所叙述的【for i in range(n)表示的是以inputs中的每一个num为起始,去枚举所有的lists.】,由于有两个1,其实在枚举以第一个1为开始的所有lists的时候已经包括了所有的可能,所以就不用再去列举以第二个1为起始的所有lists。
python
if i > 0 and inputs[i] == inputs[i-1]:#因为candidates中有重复元素,所以有一个枝剪的过程
continue
python
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
output = []
def dfs(inputs,lists, sums):
if sums == target:
output.append(lists)
return
n = len(inputs)
for i in range(n):
if i > 0 and inputs[i] == inputs[i-1]:#因为candidates中有重复元素,所以有一个枝剪的过程
continue
if sums + inputs[i] > target: #枝剪
return
dfs(inputs[i+1:],lists + [inputs[i]], sums + inputs[i]) #表示可以选自己
dfs(candidates,[],0)
return output
第三题:

可以用dfs的做法,可以这么写的原因:
- 每一个元素是可以重复取的,所以dfs的内循环中采用的是for num in nums,也就是可以重复的取num(自己)
- 求取的是排列的个数,因此lists中元素一致但是顺序不一样也是可以的。
python
class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
nums.sort()
output = []
def dfs(lists, sums):
if sums == target:
output.append(lists)
return
for num in nums:
if num + sums > target:
return
dfs(lists + [num], sums + num)
dfs([],0)
return len(output)