• [LeetCode] 39. 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]
    ]

    对于一个给出的数target和一个数集C,问存在多少种不同的方案,使得可以从数集C中选出若干个数(每个数可以选择无限次)使得这些数的和等于target。

    新题中没有:

    • Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).

    如果有这个要求就要对数组C排序,使用过的就不能在使用了,因为会要保证大小顺序。

    解法:递归 + backtracking,  注意数组的mutable.

    Java:

    public class Solution {
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
            List<List<Integer>> res = new ArrayList<>();
            if (candidates == null) return res;
            Arrays.sort(candidates);
            getCombinations(res, new ArrayList<>(), candidates, target, 0);
            return res;
        }
        
        private void getCombinations(List<List<Integer>> res, List<Integer> list, int[] nums, int target, int pos) {
            if (target < 0) return;
            if (target == 0) {
                res.add(new ArrayList<>(list));
                return;
            }
            for (int i = pos; i < nums.length; i++) {
                if (nums[i] > target) break;
                if (i > pos && nums[i] == nums[i - 1]) continue;
                list.add(nums[i]);
                getCombinations(res, list, nums, target - nums[i], i);
                list.remove(list.size() - 1);
            }
        }
    }
    

    Python:

    class Solution:
        # @param candidates, a list of integers
        # @param target, integer
        # @return a list of lists of integers
        def combinationSum(self, candidates, target):
            result = []
            self.combinationSumRecu(sorted(candidates), result, 0, [], target)
            return result
        
        def combinationSumRecu(self, candidates, result, start, intermediate, target):
            if target == 0:
                result.append(list(intermediate))
            while start < len(candidates) and candidates[start] <= target:
                intermediate.append(candidates[start])
                self.combinationSumRecu(candidates, result, start, intermediate, target - candidates[start])
                intermediate.pop()
                start += 1  

    Python: wo

    class Solution(object):
        def combinationSum(self, candidates, target):
            """
            :type candidates: List[int]
            :type target: int
            :rtype: List[List[int]]
            """
            res = []        
            self.helper(res, sorted(candidates), [], 0, 0, target)      
            return res
        
        def helper(self, res, candidates, cur, temp, pos, target):
            if temp > target:
                return
            if temp == target:
                res.append(cur)
                
            for i in range(pos, len(candidates)):
                self.helper(res, candidates, cur + [candidates[i]], temp + candidates[i], i, target)  

    C++:

    class Solution {
    public:
        vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
            // 注意candidates不是有序的,要先排序处理
            sort(candidates.begin(), candidates.end());
            // 用以记录答案和当前方案
            vector<vector<int>> ans;
            vector<int> current;
            // 开始回溯搜索
            backtracking(ans, candidates, current, 0, target);
            // 返回答案
            return ans;
        }
        
        void backtracking(vector<vector<int>>& ans, vector<int>& candidates, vector<int> current, int last_use, int rest_target) {
            // 当rest_target等于0时,说明已经找到了一组合法的方案
            if (rest_target == 0) {
                // 故将其加入到答案当中
                ans.push_back(current);
            }
            // 否则就枚举下一个加入到current中的数,在枚举中注意2个条件
            // i >= last_use,保证current是非递减的
            // candidates[i] <= rest_target,保证rest_target不小于0
            for (int i = last_use; i < candidates.size() && candidates[i] <= rest_target; i++) {
                // 放入current中
                current.push_back(candidates[i]);
                // 继续搜索下一个数字
                backtracking(ans, candidates, current, i, rest_target - candidates[i]);
                // 回溯处理
                current.pop_back();
            }
        }
    };
    

       

    类似题目:

    [LeetCode] 40. Combination Sum II 组合之和 II

    [LeetCode] 216. Combination Sum III 组合之和 III

    [LeetCode] 377. Combination Sum IV 组合之和 IV

    [LeetCode] 78. Subsets 子集合

    [LeetCode] 90. Subsets II 子集合 II

    [LeetCode] 46. Permutations 全排列

    [LeetCode] 47. Permutations II 全排列 II

    [LeetCode] 131. Palindrome Partitioning 回文分割

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    浅析Java中的final关键字
    浅谈JAVA集合框架
    While reading XXX pngcrush caught libpng error: N
    git/svn里面的merge和rebase区别
    kvc kvo 总结---180313
    iOS 拨打电话三种方式总结
    IOS中获取各种文件的目录路径的方法-备
    文件管理系统-备
    iOS界面调试工具 Reveal-备用
    十六进制string转换UIColor -备用
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8674180.html
Copyright © 2020-2023  润新知