code39:Combination Sum
Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
The same repeated number may be chosen from candidates unlimited number of times.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
Example 1:
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[
[7],
[2,2,3]
]
Example 2:
Input: candidates = [2,3,5], target = 8,
A solution set is:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
解答:
首先想到使用divmod解题:
如果mod!=0,则在数组中遍历找到对应的数组成数组。
如果等于0,则返回div个单元素组成的数组。
咋一看感觉没问题,但是实测时发现,和可以由多个元素组成,这种解法只涵盖了两个。
再次考虑,发现可以使用循环迭代,即每次减去数组一个元素,然后看residual再遍历数组减去元素,知道residual为0时返回所以减去的值作为一个 答案数组。最后将答案数组组合起来形成结果返回。
实现:
发现使用递归将会很简单(类似于backtracking,dfs的解法)
1 定义一个全局变量temp_arr=[]作为最后的结果
2 再带入递归。因为递归要返回每层的值组成的数组。所以设置一个新的参数last_arr用来接收上一个递归里面的现有数组。
3 终止条件:如果residual==0则last_arr+当前元素。然后放入temp_arr中;
或者residual<0 则break(表示不再进行变换,当前的last_arr废弃)
4 递归条件:如果residual>0则last_arr+=当前元素,传入的遍历数组变为当前元素开始(这里注意,先将数组进行排序,然后这样操作下可以避免结果的重复)
代码:
class Solution:
def combinationSum(self, candidates, target: int):
candidates = sorted(candidates)
# res_arr = []
global temp_arr
temp_arr = []
self.search(candidates, target, [])
return temp_arr
def search(self, candidates, target, last_arr):
global temp_arr
for i in range(len(candidates)):
residual = target - candidates[i]
#print(residual)
if residual == 0:
#print(last_arr + [candidates[i]])
temp_arr.append(last_arr + [candidates[i]])
break
elif residual > 0:
self.search(candidates[i:], residual, last_arr + [candidates[i]])
else:
break
tips:
在遍历循环中有if else判断时,要注意是否加break跳出循环。此时加了break以后,不会再进行之后的操作了,可以减少时间复杂度(同一个数量级但是实际更短)
global变量可以提供远程的修改。如果不想这样操作,可以作为参数传入。
code40: Combination Sum II
Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
Each number in candidates may only be used once in the combination.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
Example 1:
Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
Example 2:
Input: candidates = [2,5,2,1,2], target = 5,
A solution set is:
[
[1,2,2],
[5]
]
解答:
类似于上一题,
区别:数组可重复,每个只能使用一次。
可重复使用一次,去重:
1 使用list(set([tuple(t) for t in temp]))来做二维数组的去重
2 或者在判定条件内添加如果前后一样就不用做该元素的操作了
代码:
class Solution:
def combinationSum2(self, candidates, target: int):
global temp
temp = []
candidates.sort()
#candidates = list(set(candidates))
self.search(candidates, target, [])
#temp = list(set([tuple(t) for t in temp]))
temp = list(set([tuple(t) for t in temp]))
return temp
def search(self, arr, tar, last_arr):
global temp
for i in range(len(arr)):
residual = tar - arr[i]
if residual == 0:
temp.append([arr[i]] + last_arr)
break
elif residual > 0:
self.search(arr[i + 1:], residual, last_arr + [arr[i]])
else:
break