leetcode-pp / 91alg-5-daily-check

91 天学算法第五期打卡
55 stars 14 forks source link

【Day 80 】2021-11-28 - 39 组合总和 #99

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

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

zszs97 commented 2 years ago

开始刷题

题目简介

【Day 80 】2021-11-28 - 39 组合总和

题目思路

题目代码

代码块

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;
    }
};

复杂度

cassiechris commented 2 years ago

思路

学习题解

代码

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;
15691894985 commented 2 years ago

【day80】题目地址(39 组合总和)

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

复杂度分析:

Zhang6260 commented 2 years ago

JAVA版本

思路:

主要使用回溯+剪枝,使用剪枝的前提必须是有序的数组。

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);
        }

    }
}
RonghuanYou commented 2 years ago
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
ZJP1483469269 commented 2 years ago

思路

回溯

代码

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);
            }
        }
    }
}
shamworld commented 2 years ago
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;
};
Menglin-l commented 2 years ago

剪枝+回溯


代码部分:

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);
        }
    }
}

复杂度:

Time: O(2 ^ N)

Space: O(N)

kennyxcao commented 2 years ago

39. Combination Sum

Intuition

Code

/**
 * @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
  }
}

Complexity Analysis

TimmmYang commented 2 years ago

思路

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
mokrs commented 2 years ago
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();
    }
}
shawncvv commented 2 years ago

思路

回溯

代码

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;
};

复杂度

BpointA commented 2 years ago

思路

回溯

代码

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
shixinlovey1314 commented 2 years ago

Title:39. Combination Sum

Question Reference LeetCode

Solution

Backtracing, at each level, attampt to add each item into the path, if the cur sum has excced the target, stop probing.

Code

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()); 
    }
};

Complexity

Time Complexity and Explanation

Space Complexity and Explanation

Francis-xsc commented 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;
    }
};

复杂度分析

L-SUI commented 2 years ago

/**

kbfx1234 commented 2 years ago

39. 组合总和

// 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;
    }
};
BreezePython commented 2 years ago

思路

回溯

代码

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

复杂度

asterqian commented 2 years ago

思路

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;
    }
};
时间复杂度 O(n^target/min)
空间复杂度 O(target/min)
xinhaoyi commented 2 years ago

class Solution { List<List> res = new ArrayList<>(); //记录答案 List path = new ArrayList<>(); //记录路径

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); //回溯,恢复现场
        }
    }
}

}

leo173701 commented 2 years ago
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
ChenJingjing85 commented 2 years ago
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
HouHao1998 commented 2 years ago
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);
        }
    }
}
KennethAlgol commented 2 years ago

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();
        }
    }

}
jaysonss commented 2 years ago

思路

完全无剪枝版本:记录下所有结果(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;
        }
    }
}
heyqz commented 2 years ago
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()
machuangmr commented 2 years ago

思路

xj-yan commented 2 years ago
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);
        }

    }
}
flagyk5 commented 2 years ago
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
liudi9047 commented 2 years ago

public List<List> combinationSum(int[] candidates, int target) { List<List> results = new ArrayList<>(); LinkedList comb = new LinkedList<>(); this.backtrack(target, comb, 0, candidates, results); return results; }

private void backtrack(int remain, LinkedList comb, int start, int[] candidates, List<List> results) { if (remain == 0) { results.add(new ArrayList(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(); } }

dongzegithub commented 2 years ago
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);
        }

    }
}
freedom0123 commented 2 years ago
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);
        }

    }
}
yibenxiao commented 2 years ago

【Day 80】39 组合总和

代码

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)

falsity commented 2 years ago
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);
        }
    }
}
chaggle commented 2 years ago

title: "Day 80 39. 组合总和" date: 2021-11-29T17:31:34+08:00 tags: ["Leetcode", "c++", "recursion"] categories: ["91-day-algorithm"] draft: true


39. 组合总和

题目

给定一个无重复元素的正整数数组 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;
    }
};

复杂度

winterdogdog commented 2 years ago

回溯

/**
 * @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
};
brainlds commented 2 years ago

class Solution { public List<List> combinationSum(int[] candidates, int target) { List<List> ans = new ArrayList<List>(); List combine = new ArrayList(); 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);
    }
}

}

wangwiitao commented 2 years ago

回溯

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;
}
HWFrankFung commented 2 years ago

Codes

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;
};
Richard-LYF commented 2 years ago

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;
ZETAVI commented 2 years ago
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);
            }
        }
    }
}
wangyifan2018 commented 2 years ago
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;
hellowxwworld commented 2 years ago

思路

回溯

代码

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;
}
BreezePython commented 2 years ago

思路

字符串枚举

代码

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

复杂度

Bingbinxu commented 2 years ago

思路 回溯算法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