zoukankan      html  css  js  c++  java
  • 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;
        }
    };
  • 相关阅读:
    高放的c++学习笔记之函数基础
    高放的c++学习笔记之关联容器
    高放的c++学习笔记之lambda表达式
    二分图小结
    送给大一学弟学妹的几句话
    网络流小结
    后缀数组小结
    hdu5353
    UVALive 5792 Diccionário Portuñol
    概率dp小结
  • 原文地址:https://www.cnblogs.com/yaoyudadudu/p/9103182.html
Copyright © 2011-2022 走看看