Open azl397985856 opened 2 years ago
class Solution {
public:
void dfs(vector<int>& candidates, int target, vector<vector<int>>& ans, vector<int>& combine, int idx) {
if (idx == candidates.size()) {
return;
}
if (target == 0) {
ans.emplace_back(combine);
return;
}
// 直接跳过
dfs(candidates, target, ans, combine, idx + 1);
// 选择当前数
if (target - candidates[idx] >= 0) {
combine.emplace_back(candidates[idx]);
dfs(candidates, target - candidates[idx], ans, combine, idx);
combine.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> combine;
dfs(candidates, target, ans, combine, 0);
return ans;
}
};
学习题解
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def backtrack(ans,tempList, candidates, remain, start):
if remain < 0: return
elif remain == 0: return ans.append(tempList.copy())
for i in range(start, len(candidates)):
tempList.append(candidates[i])
backtrack(ans, tempList, candidates, remain - candidates[i], i)
tempList.pop()
ans = [];
backtrack(ans, [], candidates, target, 0);
return ans;
https://leetcode-cn.com/problems/combination-sum/
每个元素可用无限次,回溯+合适的减枝操作
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def backtracking(n, curr, start):
if n < 0: return
if n == 0: return result.append(curr[:])
for i in range(start, len(candidates)):
curr.append(candidates[i])
backtracking(n - candidates[i], curr, i)
curr.pop()
result = []
backtracking(target, [], 0)
return result
复杂度分析:
主要使用回溯+剪枝,使用剪枝的前提必须是有序的数组。
class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { if(candidates==null||candidates.length==0){ return null; } Arrays.sort(candidates); List<List<Integer>> res = new ArrayList<>(); dfs(res,candidates,target,0,0,new ArrayList<>()); return res; } public void dfs(List<List<Integer>> list,int[]candidates,int target,int temp,int start,List<Integer> t_list){ if(temp==target){ ArrayList<Integer> t= new ArrayList<Integer>(t_list); if(!list.contains(t))list.add(t); }else if(temp>target){ return; } for(int i=start;i<candidates.length;i++){ //这里进行预处理一下 前提是必须是有序数组 if(temp+candidates[i]>target){ break; } t_list.add(candidates[i]); dfs(list,candidates,target,temp+candidates[i],i,t_list); t_list.remove(t_list.size()-1); } } }
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def dfs(remain, path):
if remain == 0:
res.append(path)
for n in candidates:
if n > remain:
break
if path and n < path[-1]:
continue
dfs(remain - n, path + [n])
res = []
candidates.sort()
dfs(target, [])
return res
回溯
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
backtrack(res, list, candidates, target, 0);
return res;
}
public void backtrack(List<List<Integer>> res , List<Integer> list , int[] candidates, int cur ,int pos){
if(cur < 0) return;
if(cur == 0){
res.add(new ArrayList<>(list));
return ;
}
else{
for(int i = pos; i < candidates.length ; i++){
list.add(candidates[i]);
backtrack(res,list,candidates,cur - candidates[i],i);
list.remove(list.size()-1);
}
}
}
}
var combinationSum = function(candidates, target) {
const ans = [];
const dfs = (target, combine, idx) => {
if (idx === candidates.length) {
return;
}
if (target === 0) {
ans.push(combine);
return;
}
// 直接跳过
dfs(target, combine, idx + 1);
// 选择当前数
if (target - candidates[idx] >= 0) {
dfs(target - candidates[idx], [...combine, candidates[idx]], idx);
}
}
dfs(target, [], 0);
return ans;
};
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
if (candidates.length == 0 || candidates == null) return res;
List<Integer> path = new ArrayList<>();
Arrays.sort(candidates);
searchCombinationSum(candidates, target, 0, 0, path, res);
return res;
}
public void searchCombinationSum(int[] candidates, int target, int pathSum, int index, List<Integer> path, List<List<Integer>> res) {
if (pathSum == target) {
res.add(new ArrayList<>(path));
return;
}
for (int i = index; i < candidates.length; i ++) {
pathSum += candidates[i];
if (pathSum > target) break;
path.add(candidates[i]);
searchCombinationSum(candidates, target, pathSum, i, path, res);
pathSum -= candidates[i];
path.remove(path.size() - 1);
}
}
}
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
const combinationSum = function(candidates, target) {
const results = [];
if (!candidates || candidates.length === 0) return results;
candidates.sort((a, b) => a - b);
comboSearch(candidates, target, 0, [], results);
return results;
};
function comboSearch(candidates, target, start, path, results) {
if (target === 0) results.push(path.slice(0));
if (target <= 0) return;
for (let i = start; i < candidates.length; i++) {
if (candidates[i] > target) break; // sorted so later values are impossible
path.push(candidates[i]);
comboSearch(candidates, target - candidates[i], i, path, results); // not i+1, can reuse same elements
path.pop(); // backtrack
}
}
DFS
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
res = []
candidates.sort()
def helper(i, cur, path):
if cur == target:
res.append(path)
for j in range(i, len(candidates)):
if cur + candidates[j] > target:
return
helper(j, cur + candidates[j], path + [candidates[j]])
helper(0, 0, [])
return res
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> res;
vector<int> combine;
dfs(candidates, target, res, combine, 0);
return res;
}
void dfs(vector<int>& candidates, int target, vector<vector<int>>& res, vector<int>& combine, int idx) {
if (idx == candidates.size()) {
return;
}
if (target == 0) {
res.emplace_back(combine);
return;
}
dfs(candidates, target, res, combine, idx + 1);
if (target - candidates[idx] >= 0) {
combine.emplace_back(candidates[idx]);
dfs(candidates, target - candidates[idx], res, combine, idx);
combine.pop_back();
}
}
回溯
JavaScript Code
function backtrack(list, tempList, nums, remain, start) {
if (remain < 0) return;
else if (remain === 0) return list.push([...tempList]);
for (let i = start; i < nums.length; i++) {
tempList.push(nums[i]);
backtrack(list, tempList, nums, remain - nums[i], i); // 数字可以重复使用
tempList.pop();
}
}
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function (candidates, target) {
const list = [];
backtrack(
list,
[],
candidates.sort((a, b) => a - b),
target,
0
);
return list;
};
复杂度
回溯
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
result=[]
m=len(candidates)
def back(start,path):
if sum(path)>target:
return
if sum(path)==target:
if path[:] not in result:
result.append(path[:])
return
for i in range(start,m):
path.append(candidates[i])
back(i,path)
path.pop()
path=[]
back(0,path)
return result
Backtracing, at each level, attampt to add each item into the path, if the cur sum has excced the target, stop probing.
class Solution {
public:
set<vector<int>> comb;
void getSum(vector<int>& candidates, int target, vector<int> path, int cur) {
if (cur == target) {
sort(path.begin(), path.end());
comb.insert(path);
return;
}
if(cur > target) {
return;
}
for (int i = 0; i < candidates.size(); i++) {
path.push_back(candidates[i]);
getSum(candidates, target, path, cur + candidates[i]);
path.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<int> path;
getSum(candidates, target, path, 0);
return vector<vector<int>>(comb.begin(), comb.end());
}
};
回溯
class Solution {
public:
void dfs(vector<int>& candidates, int target, vector<vector<int>>& ans, vector<int>& combine, int idx) {
if (idx == candidates.size()) {
return;
}
if (target == 0) {
ans.emplace_back(combine);
return;
}
dfs(candidates, target, ans, combine, idx + 1);
if (target - candidates[idx] >= 0) {
combine.emplace_back(candidates[idx]);
dfs(candidates, target - candidates[idx], ans, combine, idx);
combine.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> combine;
dfs(candidates, target, ans, combine, 0);
return ans;
}
};
复杂度分析
/**
@return {number[][]} */ var combinationSum = function(candidates, target) { const ans = []; const dfs = (target, combine, idx) => { if (idx === candidates.length) { return; } if (target === 0) { ans.push(combine); return; } // 直接跳过 dfs(target, combine, idx + 1); // 选择当前数 if (target - candidates[idx] >= 0) { dfs(target - candidates[idx], [...combine, candidates[idx]], idx); } }
dfs(target, [], 0); return ans; };
// 11-28 cpp 剪枝
class Solution {
public:
vector<vector<int>> ans;
vector<int> temp;
void backtrack(vector<int> &candidates, int target, int sum, int startidx) {
// 终止条件
if (sum == target) {
ans.push_back(temp);
return;
}
// 剪枝
for (int i = startidx; i < candidates.size() && sum + candidates[i] <= target; i++) {
sum += candidates[i];
temp.push_back(candidates[i]);
//由于每一个元素可以重复使用,下一轮搜索的起点依然是 i
backtrack(candidates, target, sum, i);
// 回溯
sum -= candidates[i];
temp.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
int len = candidates.size();
sort(candidates.begin(),candidates.end()); //排序
backtrack(candidates, target, 0, 0);
return ans;
}
};
回溯
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def dfs(candidates, begin, size, path, res, target):
if target < 0:
return
if target == 0:
res.append(path)
return
for index in range(begin, size):
dfs(candidates, index, size, path + [candidates[index]], res, target - candidates[index])
size = len(candidates)
if size == 0:
return []
path = []
res = []
dfs(candidates, 0, size, path, res, target)
return res
See Comments
class Solution {
public:
void backtrack(vector<vector<int>>& res, vector<int>& v, vector<int>& candidates,int curr, int pos) {
// case if cannot be added up to target
if (curr < 0) return;
// answer vector found
if (curr == 0) {
res.push_back(v);
return;
}
// pos for not giving repeating answer combos
for (int i = pos; i < candidates.size(); ++i) {
v.push_back(candidates[i]);
backtrack(res, v, candidates, curr - candidates[i], i);
v.pop_back(); // recover
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> res;
vector<int> v;
backtrack(res, v, candidates, target, 0);
return res;
}
};
class Solution {
List<List
public List<List<Integer>> combinationSum(int[] candidates, int target) {
dfs(candidates,0, target);
return res;
}
public void dfs(int[] c, int u, int target) {
if(target < 0) return ;
if(target == 0)
{
res.add(new ArrayList(path));
return ;
}
for(int i = u; i < c.length; i++){
if( c[i] <= target)
{
path.add(c[i]);
dfs(c,i,target - c[i]); // 因为可以重复使用,所以还是i
path.remove(path.size()-1); //回溯,恢复现场
}
}
}
}
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
res= []
can = sorted(list(set(candidates)))
n = len(can)
def dfs(can, path, startindex, remain):
if remain==0:
res.append(path[:])
for i in range(startindex, n):
if can[i]>remain: #用来剪枝加速
break
path.append(can[i])
dfs(can,path,i,remain-can[i])
path.pop()
dfs(can,[],0,target)
return res
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def dfs(candidates, begin, size, path, res, target):
if target < 0:
return
if target == 0:
res.append(path)
return
for index in range(begin, size):
dfs(candidates, index, size, path + [candidates[index]], res, target - candidates[index])
size = len(candidates)
if size == 0:
return []
path = []
res = []
dfs(candidates, 0, size, path, res, target)
return res
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
List<Integer> combine = new ArrayList<Integer>();
dfs(candidates, target, ans, combine, 0);
return ans;
}
public void dfs(int[] candidates, int target, List<List<Integer>> ans, List<Integer> combine, int idx) {
if (idx == candidates.length) {
return;
}
if (target == 0) {
ans.add(new ArrayList<Integer>(combine));
return;
}
// 直接跳过
dfs(candidates, target, ans, combine, idx + 1);
// 选择当前数
if (target - candidates[idx] >= 0) {
combine.add(candidates[idx]);
dfs(candidates, target - candidates[idx], ans, combine, idx);
combine.remove(combine.size() - 1);
}
}
}
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> results = new ArrayList<>();
LinkedList<Integer> comb = new LinkedList<>();
this.backtrack(target, comb, 0, candidates, results);
return results;
}
private void backtrack(int remain, LinkedList<Integer> comb, int start, int[] candidates, List<List<Integer>> results) {
if (remain == 0) {
results.add(new ArrayList<Integer>(comb));
return;
} else if (remain < 0) {
return;
}
for (int i = start; i < candidates.length; ++i) {
comb.add(candidates[i]);
this.backtrack(remain - candidates[i], comb, i, candidates, results);
comb.removeLast();
}
}
}
完全无剪枝版本:记录下所有结果(list sort后toString(),缓存到Hash表里), 去重后返回结果
通过控制索引剪掉重复结果
数组排序后,判断如果target-num<0就终止遍历从而进一步剪枝
代码:
class Solution {
List<List<Integer>> ans = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
LinkedList<Integer> ret = new LinkedList<>();
Arrays.sort(candidates);
dfs(candidates,target,ret,0);
return ans;
}
private void dfs(int[] candidates, int target,LinkedList<Integer> ret,int idx) {
if(target == 0){
ans.add(new ArrayList(ret));
return;
}
for(int i=idx;i<candidates.length;i++){
int num = candidates[i];
ret.add(num);
boolean valid = target - num >= 0;
if(valid){
dfs(candidates,target-num,ret,i);
}
ret.removeLast();
//排序后的数组可以直接剪枝
if(!valid)break;
}
}
}
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
res, cur = [], []
candidates.sort()
self.dfs(candidates, target, 0, cur, res)
return res
def dfs(self, candidates, target, s, cur, res):
if target == 0:
res.append(cur.copy())
return
for i in range(s, len(candidates)):
if candidates[i] > target: break
cur.append(candidates[i])
self.dfs(candidates, target - candidates[i], i, cur, res)
cur.pop()
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
int len = candidates.length;
List<List<Integer>> res = new ArrayList<>();
if (len == 0) {
return res;
}
Deque<Integer> path = new ArrayDeque<>();
dfs(candidates, 0, len, target, path, res);
return res;
}
public void dfs(int[] candidates, int begin, int length, int target, Deque path, List<List<Integer>> res) {
// 递归结束的条件, 当前的值 为0的时候,
if (target < 0) return ;
if (target == 0) {
res.add(new ArrayList<>(path));
return;
}
for(int i = begin;i < length;i++) {
path.addLast(candidates[i]);
dfs(candidates, i, length, target - candidates[i], path, res);
path.removeLast();
}
}
}
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(candidates);
dfs(result, new ArrayList<>(), candidates, 0, 0, target);
return result;
}
private void dfs(List<List<Integer>> result, List<Integer> sub, int[] nums, int startIndex, int sum, int target){
if (sum == target){
result.add(new ArrayList<>(sub));
return;
}
for (int i = startIndex; i < nums.length; i++){
if (sum + nums[i] > target) continue;
sub.add(nums[i]);
dfs(result, sub, nums, i, sum + nums[i], target);
sub.remove(sub.size() - 1);
}
}
}
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def backtrack(ans,tempList, candidates, remain, start):
if remain < 0: return None
elif remain == 0: return ans.append(tempList.copy())
for i in range(start, len(candidates)):
tempList.append(candidates[i])
backtrack(ans, tempList, candidates, remain - candidates[i], i)
tempList.pop()
ans = []
backtrack(ans, [], candidates, target, 0)
return ans
public List<List
private void backtrack(int remain, LinkedList
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(candidates);
dfs(result, new ArrayList<>(), candidates, 0, 0, target);
return result;
}
private void dfs(List<List<Integer>> result, List<Integer> sub, int[] nums, int startIndex, int sum, int target){
if (sum == target){
result.add(new ArrayList<>(sub));
return;
}
for (int i = startIndex; i < nums.length; i++){
if (sum + nums[i] > target) continue;
sub.add(nums[i]);
dfs(result, sub, nums, i, sum + nums[i], target);
sub.remove(sub.size() - 1);
}
}
}
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(candidates);
dfs(result, new ArrayList<>(), candidates, 0, 0, target);
return result;
}
private void dfs(List<List<Integer>> result, List<Integer> sub, int[] nums, int startIndex, int sum, int target){
if (sum == target){
result.add(new ArrayList<>(sub));
return;
}
for (int i = startIndex; i < nums.length; i++){
if (sum + nums[i] > target) continue;
sub.add(nums[i]);
dfs(result, sub, nums, i, sum + nums[i], target);
sub.remove(sub.size() - 1);
}
}
}
class Solution {
public:
void dfs(vector<int>& candidates, int target, vector<vector<int>>& ans, vector<int>& combine, int idx) {
if (idx == candidates.size()) {
return;
}
if (target == 0) {
ans.emplace_back(combine);
return;
}
// 直接跳过
dfs(candidates, target, ans, combine, idx + 1);
// 选择当前数
if (target - candidates[idx] >= 0) {
combine.emplace_back(candidates[idx]);
dfs(candidates, target - candidates[idx], ans, combine, idx);
combine.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> combine;
dfs(candidates, target, ans, combine, 0);
return ans;
}
};
时间复杂度:最坏情况:O(N*2^N)
空间复杂度:O(N)
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
List<Integer> combine = new ArrayList<Integer>();
dfs(candidates, target, ans, combine, 0);
return ans;
}
public void dfs(int[] candidates, int target, List<List<Integer>> ans, List<Integer> combine, int idx) {
if (idx == candidates.length) {
return;
}
if (target == 0) {
ans.add(new ArrayList<Integer>(combine));
return;
}
dfs(candidates, target, ans, combine, idx + 1);
if (target - candidates[idx] >= 0) {
combine.add(candidates[idx]);
dfs(candidates, target - candidates[idx], ans, combine, idx);
combine.remove(combine.size() - 1);
}
}
}
title: "Day 80 39. 组合总和" date: 2021-11-29T17:31:34+08:00 tags: ["Leetcode", "c++", "recursion"] categories: ["91-day-algorithm"] draft: true
给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。
candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。
对于给定的输入,保证和为 target 的唯一组合数少于 150 个。
示例 1:
输入: candidates = [2,3,6,7], target = 7
输出: [[7],[2,2,3]]
示例 2:
输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]
示例 3:
输入: candidates = [2], target = 1
输出: []
示例 4:
输入: candidates = [1], target = 1
输出: [[1]]
示例 5:
输入: candidates = [1], target = 2
输出: [[1,1]]
提示:
1 <= candidates.length <= 30
1 <= candidates[i] <= 200
candidate 中的每个元素都是独一无二的。
1 <= target <= 500
- 1、经典递归算法
class Solution {
public:
void dfs(vector<int>& candidates, int target, vector<vector<int>>& ans, vector<int>& combine, int idx) {
if (idx == candidates.size()) return;
if (target == 0) {
ans.emplace_back(combine);
return;
}
dfs(candidates, target, ans, combine, idx + 1);
if (target - candidates[idx] >= 0) {
combine.emplace_back(candidates[idx]);
dfs(candidates, target - candidates[idx], ans, combine, idx);
combine.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> combine;
dfs(candidates, target, ans, combine, 0);
return ans;
}
};
回溯
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function(candidates, target) {
let res = [];
let dfs = (candidates, target, temp, index) => {
if (target === 0) {
res.push(temp.slice())
} else if (target > 0) {
for(let i = index; i < candidates.length; i++) {
temp.push(candidates[i]);
dfs(candidates, target - candidates[i], temp, i)
temp.pop()
}
}
}
dfs(candidates, target, [], 0)
return res
};
class Solution {
public List<List
public void dfs(int[] candidates, int target, List<List<Integer>> ans, List<Integer> combine, int idx) {
if (idx == candidates.length) {
return;
}
if (target == 0) {
ans.add(new ArrayList<Integer>(combine));
return;
}
dfs(candidates, target, ans, combine, idx + 1);
if (target - candidates[idx] >= 0) {
combine.add(candidates[idx]);
dfs(candidates, target - candidates[idx], ans, combine, idx);
combine.remove(combine.size() - 1);
}
}
}
const combinationSum = (candidates, target) => {
const res = [];
const dfs = (start, temp, sum) => {
if (sum >= target) {
if (sum == target) {
res.push(temp.slice());
}
return;
}
for (let i = start; i < candidates.length; i++) {
temp.push(candidates[i]);
dfs(i, temp, sum + candidates[i]);
temp.pop();
}
};
dfs(0, [], 0);
return res;
}
const combinationSum = (candidates, target) => {
const len = candidates.length;
const res = [];
candidates.sort((a, b) => a - b);
const search = (path, target, start) => {
if (target === 0) {
res.push([...path]);
return;
}
for (let i = start; i < len; i++) {
if (target < candidates[i]) return;
path.push(candidates[i]);
search(path, target - candidates[i], i);
path.pop();
}
};
search([], target, 0);
return res;
};
class Solution: def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: def backtrack(ans,tempList, candidates, remain, start): if remain < 0: return elif remain == 0: return ans.append(tempList.copy()) # 将部分解空间合并到总体的解空间
for i in range(start, len(candidates)):
tempList.append(candidates[i])
backtrack(ans, tempList, candidates, remain - candidates[i], i)# 数字可以重复使用
tempList.pop()
ans = [];
backtrack(ans, [], candidates, target, 0);
return ans;
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
dfs(candidates, target, 0, new ArrayList<>(), res, 0);
return res;
}
private void dfs(int nums[], int target, int idx, List<Integer> build, List<List<Integer>> res, int sum) {
if (sum == target) {
res.add(new ArrayList<>(build));
return;
} else if (idx == nums.length) {
return;
}
for (int i = 0; sum + i * nums[idx] <= target; ++i) {
for (int j = 0; j < i; ++j) {
build.add(nums[idx]);
}
dfs(nums, target, idx + 1, build, res, sum + i * nums[idx]);
for (int j = 0; j < i; ++j) {
build.remove(build.size() - 1);
}
}
}
}
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def backtrack(ans,tempList, candidates, remain, start):
if remain < 0: return
elif remain == 0: return ans.append(tempList.copy()) # 将部分解空间合并到总体的解空间
# 枚举所有以 i 为开始的部分解空间
for i in range(start, len(candidates)):
tempList.append(candidates[i])
backtrack(ans, tempList, candidates, remain - candidates[i], i)# 数字可以重复使用
tempList.pop()
ans = [];
backtrack(ans, [], candidates, target, 0);
return ans;
回溯
void backtrace(int start, vector<int>& candidates, int target, int& sum, vector<int>& sumArray, vector<vector<int>>& res) {
if (sum >= target) {
if (sum == target)
res.push_back(sumArray);
return ;
}
for (int i = start; i < candidates.size(); ++i) {
sumArray.push_back(candidates[i]);
sum += candidates[i];
backtrace(i, candidates, target, sum, sumArray, res);
sum -= candidates[i];
sumArray.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> res;
vector<int> sumArray;
int sum = 0;
sort(candidates.begin(), candidates.end());
backtrace(0, candidates, target, sum, sumArray, res);
return res;
}
字符串枚举
class Solution:
def strStr(self, haystack, needle):
if not needle:
return 0
left = 0
right = len(needle)
while right <= len(haystack):
if haystack[left:right] == needle:
return left
left += 1
right += 1
return -1
思路 回溯算法dfs 代码(C++)
实现语言: C++
class Solution {
vector<vector<int>> res;
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<int> curGroup;
dfs(candidates, target, curGroup, 0, 0);
return res;
}
void dfs(vector<int>& candidates, int target, vector<int>& curGroup, int sum, int index)
{
if (sum > target)
return;
if (sum == target)
res.push_back(curGroup);
else
{
for (int i = index; i < candidates.size(); i++)
{
curGroup.push_back(candidates[i]);
dfs(candidates, target, curGroup, sum + candidates[i], i);
curGroup.pop_back(); //清空方便下次从头计算
}
}
}
};
复杂度分析 时间复杂度:O(n^(target/min)),n为candidates数组的长度,min为数组中最小元素,target/min为递归栈的最大深度 空间复杂度:O(target/min),记录路径信息的list的长度不超过target/min
39 组合总和
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/combination-sum/
前置知识
题目描述
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。 解集不能包含重复的组合。 示例 1:
输入:candidates = [2,3,6,7], target = 7, 所求解集为: [ [7], [2,2,3] ] 示例 2:
输入:candidates = [2,3,5], target = 8, 所求解集为: [ [2,2,2,2], [2,3,3], [3,5] ]
提示:
1 <= candidates.length <= 30 1 <= candidates[i] <= 200 candidate 中的每个元素都是独一无二的。 1 <= target <= 500