LeetCode Combination Sum I, II, III, IV

    xiaoxiao2022-07-12  163

    文章目录

    [39. Combination Sum](https://leetcode.com/problems/combination-sum/)[40. Combination Sum II](https://leetcode.com/problems/combination-sum-ii/)[216. Combination Sum III](https://leetcode.com/problems/combination-sum-iii/)[377. Combination Sum IV](https://leetcode.com/problems/combination-sum-iv/)

    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的集合。其中原始元素集合中无重复的元素,可以重复使用原集合中的元素。返回的结果不能有相同的集合,如[2,3,2]和[2,2,3]。

    思路:回溯法,参考A general approach to backtracking questions。因为可以使用重复的元素,因此再进行递归时从第i个元素开始。

    工程代码下载

    class Solution { public: vector<vector<int>> combinationSum(vector<int>& candidates, int target) { vector<vector<int>> res; vector<int> vec; backtracking(res, vec, candidates, 0, target); return res; } private: void backtracking(vector<vector<int>>& res, vector<int>& vec, const vector<int>& candidate, int start, int remain){ if(remain == 0){ res.push_back(vec); return; } if(remain < 0) return; for(int i = start; i < candidate.size(); ++i){ vec.push_back(candidate[i]); // not i + 1 because we can reuse same elements backtracking(res, vec, candidate, i, remain-candidate[i]); vec.pop_back(); } } };

    40. 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] ]

    题目: 给定一个候选元素的数组candidates,找出满足和为target的所有子集。candidates可能包含重复的元素,只能使用candidates中存在的元素。

    思路: 和4sum类似,只是这里的递归深度不定,递归返回的条件是remain已经等于0,参考A general approach to backtracking questions。同时由于题目的特殊性,candidates中的元素和target均为正数,所以当remain小于0时也可以直接返回,减少递归的次数。为了防止结果中出现重复的集合,先对candidates排序,同时在每层递归中跳过已经判断过的相同元素。

    工程代码下载

    #include<iostream> #include<vector> #include<algorithm> using namespace std; class Solution { public: vector<vector<int>> combinationSum2(vector<int>& candidates, int target) { sort(candidates.begin(), candidates.end()); vector<vector<int> > res; vector<int> vec; helper(candidates, res, vec, 0, target); return res; } private: void helper(vector<int>& candidates, vector<vector<int>>& res, vector<int>& vec, int start, int remain){ /** All numbers (including target) will be positive integers. **/ if(remain < 0) return; if(remain == 0){ res.push_back(vec); return; } for(int i = start; i< candidates.size(); ++i){ /** skip duplicates */ if(i > start && candidates[i] == candidate[i-1]) continue; vec.push_back(candidates[i]); helper(candidates, res, vec, i+1, remain-candidates[i]); vec.pop_back(); } } }; int main(int argc, char const *argv[]) { Solution sln; vector<int> testcase{10,1,2,7,6,1,5}; vector<vector<int>> res = sln.combinationSum2(testcase, 8); for(auto vec: res){ for(auto i : vec) cout << i << ","; cout << endl; } return 0; }

    216. Combination Sum III

    Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.

    Note:

    All numbers will be positive integers.The solution set must not contain duplicate combinations.

    Example 1:

    Input: k = 3, n = 7 Output: [[1,2,4]]

    Example 2:

    Input: k = 3, n = 9 Output: [[1,2,6], [1,3,5], [2,3,4]]

    题目:从集合{1,2,3,4,5,6,7,8,9}中选择k个数使其满足和为n,返回所有可能的组合。

    思路:回溯。类似4Sum。递归深度为k,当已经选择了k个元素之后,判断其和是否为n,如果是则将该组合保存下来并回溯,否则直接回溯返回。

    工程代码下载

    class Solution { public: vector<vector<int>> combinationSum3(int k, int n) { vector<vector<int>> res; vector<int> vec; if(k <= 0) return res; helper(res, vec, k, n, 1); return res; } private: void helper(vector<vector<int>>& res, vector<int>& vec, int k, int remain, int start){ if(k < 0 && remain < 0) return; if(k == 0){ if(remain == 0) res.push_back(vec); return; } for(int i = start; i <= 9; ++i){ vec.push_back(i); helper(res, vec, k-1, remain-i, i+1); vec.pop_back(); } } };

    377. Combination Sum IV

    Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

    Example:

    nums = [1, 2, 3] target = 4 The possible combination ways are: (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 3) (2, 1, 1) (2, 2) (3, 1) Note that different sequences are counted as different combinations. Therefore the output is 7.

    Follow up: What if negative numbers are allowed in the given array? How does it change the problem? What limitation we need to add to the question to allow negative numbers?

    题目:返回和为target的组合的个数。其中nums中无重复的元素,不同的元素排列看作是不同的组合结果。

    思路:采用前缀和的思想,参考DP Solution 。先判断和为1的组合个数,那么和为2的组合个数可以等于comb[2] = comb[1], if nums[j] =1,直到和为target。可以先对nums进行排序。

    工程代码下载

    class Solution { public: int combinationSum4(vector<int>& nums, int target) { vector<unsigned int> comb(target + 1); comb[0] = 1; for(int i = 1; i <= target; ++i){ for(int j = 0; j < nums.size(); ++j){ if(i - nums[j] >= 0) comb[i] += comb[i-nums[j]]; } } return comb[target]; } };
    最新回复(0)