Leetcode Combination系列:39 & 77 & 40 & 216 & 17

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

 

思路:

给出一组候选数字和一个目标数字, 要求返回能够组成目标数字的候选数字的组合,使用个数没有限制但是组合不能够重复。

我们可以使用DFS来解决这个问题。

为了更好的剪枝:我们可以对候选数组进行排序:由小到大的顺序。

从候选数组第一个该开始尝试:能否由含有该数字的组合构成一个和为目标数组的组合,因为对数字使用个数没有限制,我们在下一层递归中也应该从该数字开始寻找。如果target-candidates[i] < 0说明该数字与之前的数字的组合的和大于target,又因为我们对候选数组进行了排序,所以后面的较大的数字加入也一定大于目标数字,所以可以直接break。

 

代码:

class Solution {
public:
    void combinationDFS(vector<vector<int>>& ret, int target, vector<int> &candidates, vector<int> comb, int start){
        if(target == 0){
            ret.push_back(comb);
            return;
        }
        for(int i = start; i < candidates.size(); i++){
            if(target - candidates[i] < 0)
                return;
            int newT = target - candidates[i];
            comb.push_back(candidates[i]);
            combinationDFS(ret, newT, candidates, comb, i);
            comb.pop_back();
        }
        
    }
    
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        vector<vector<int>> ret;
        vector<int> comb;
        combinationDFS(ret, target, candidates, comb, 0);
        return ret;
    }

};

 

-----------------------下一道题分割线---------------------------------------

77. Combinations

问题描述:

Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.

Example:

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

 

解题思路:

给出两个整数 n 和 k, 要给出所有由 k 个 [1,n] 中的数字组成的组合。

仔细观察给出的例子中,我发现了几个额外的要求:数字不能够重复利用如1,1就不在回答中。

并且没有重复的组合。

依然适用DFS来进行搜索。 

代码:

class Solution {
public:
    void FindComb(vector<vector<int>>& ret, vector<int>& comb, int k, int n, int start){
        if(k == 0){
            ret.push_back(comb);
            return;
        }
        for(int i = start; i <= n; i++){
            comb.push_back(i);
            FindComb(ret, comb, k-1, n, i+1);
            comb.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> ret;
        if(k > n)
            return ret;
        vector<int> comb;
        FindComb(ret, comb, k, n, 1);
        return ret;
    }
};

 

-----------------------------------我是下一题分割线--------------------------------------------

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

 

解题思路:

这道题与39的不同之处为给出的备选数组中可能存在重复的数字。

如果不加处理,一定会出现重复的组合:如当寻找完1开头的数字的时候,若有不止一个1出现,则一定再寻找一遍1开头的组合。

为了解决这种问题,我加了一个if语句来限定:判定条件为:( i-1 >= 0 && candidates[i-1] == candidates[i] ) 

但是执行后发现,加了这个判定语句后,并不能成功的利用备选数组中重复的数字,也就是在递归过程中依然会跳过。

而我们想做的是跳过同一层循环内的,不跳过递归里的。

所以我又多加了一个限定:

if(i-1 >= 0 && candidates[i-1] == candidates[i] && i > start)

当然这种成功的前提是我们对候选数组进行了排序。

 

代码:

class Solution {
public:
    void findComb(vector<vector<int>> &ret, vector<int>& candidates, vector<int> &comb, int target, int start){
        if(target == 0){
            ret.push_back(comb);
            return;
        }
        for(int i = start; i < candidates.size(); i++){
            if(i-1 >= 0 && candidates[i-1] == candidates[i] && i > start)
                continue;
            if(target - candidates[i] < 0)
                return;
            comb.push_back(candidates[i]);
            findComb(ret, candidates, comb, target - candidates[i], i+1);
            comb.pop_back();
        }
    }
    
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        vector<vector<int>> ret;
        vector<int> comb;
        findComb(ret, candidates, comb, target, 0);
        return ret;
    }
};

 

----------------------------我是下一道题分割线---------------------------------------

216. Combination 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]]

 

解题思路:

感觉跟之前的没有什么差别,注意的是,从给出的例子来看,不允许组合中存在重复数字。

代码: 

class Solution {
public:
    void findComb(vector<vector<int>> &ret, vector<int> &comb, int k, int target, int start){
        if(k == 0){
            if(target == 0){
                ret.push_back(comb);
            }
            return;
        }
        for(int i = start; i < 10; i++){
            if(target - i < 0)
                return;
            comb.push_back(i);
            findComb(ret, comb, k-1, target-i, i + 1);
            comb.pop_back();
        }
    }
    
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> ret;
        vector<int> comb;
        findComb(ret, comb, k, n, 1);
        return ret;
    }
};

-------------------------------------我是下一道题分割线----------------------------------

17. Letter combinations of Phone number

问题描述:

 

Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.

A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.

Example:

Input: "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

Note:

Although the above answer is in lexicographical order, your answer could be in any order you want.

 

解题思路:

这道题多了一个小环节:就是建立数字到字母的映射,我们可以用map来实现。

其他的就差不多啦~

 

代码:

class Solution {
public:
    void findComb(string digits, int idx, vector<string> &ret, string &comb, map<int,string> &letterM){
        if(idx == digits.size()){
            ret.push_back(comb);
        }
        string letters = letterM[digits[idx] - '0'];
        for(int i = 0; i < letters.size(); i++){
            comb.push_back(letters[i]);
            findComb(digits, idx+1, ret, comb, letterM);
            comb.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
        vector<string> ret;
        if(digits.size() == 0)
            return ret;
        
        map<int, string> letter_map;
        letter_map[2] = "abc";
        letter_map[3] = "def";
        letter_map[4] = "ghi";
        letter_map[5] = "jkl";
        letter_map[6] = "mno";
        letter_map[7] = "pqrs";
        letter_map[8] = "tuv";
        letter_map[9] = "wxyz";
        
        string comb;
        findComb(digits, 0, ret, comb, letter_map);
        return ret;
    }
};

 

posted @ 2018-05-29 05:20  妖域大都督  阅读(453)  评论(0编辑  收藏  举报