美文网首页
216. Combination Sum III (M)

216. Combination Sum III (M)

作者: Ysgc | 来源:发表于2020-11-16 09:40 被阅读0次
  1. Combination Sum III
    Medium

1519

61

Add to List

Share
Find all valid combinations of k numbers that sum up to n such that the following conditions are true:

Only numbers 1 through 9 are used.
Each number is used at most once.
Return a list of all possible valid combinations. The list must not contain the same combination twice, and the combinations may be returned in any order.

Example 1:

Input: k = 3, n = 7
Output: [[1,2,4]]
Explanation:
1 + 2 + 4 = 7
There are no other valid combinations.
Example 2:

Input: k = 3, n = 9
Output: [[1,2,6],[1,3,5],[2,3,4]]
Explanation:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
There are no other valid combinations.
Example 3:

Input: k = 4, n = 1
Output: []
Explanation: There are no valid combinations. [1,2,1] is not valid because 1 is used twice.
Example 4:

Input: k = 3, n = 2
Output: []
Explanation: There are no valid combinations.
Example 5:

Input: k = 9, n = 45
Output: [[1,2,3,4,5,6,7,8,9]]
Explanation:
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 45
​​​​​​​There are no other valid combinations.

Constraints:

2 <= k <= 9
1 <= n <= 60


我的解法

class Solution {
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<bool> num_mask(9, true);
        vector<vector<int>> ret = recurr_search(k, n, num_mask);
        
        return ret;
    }
    
    vector<vector<int>> recurr_search(int k, int n, vector<bool>& num_mask) {
        vector<vector<int>> ret;
        
        if (k <= 0) {
            ret = {{}};
        }
        else if (k == 1) {
            for (int i=0; i<9; ++i) {
                if (num_mask[i] == true and i+1 == n) {
                    ret.emplace_back(vector<int>{i+1});
                }
            }
        }
        else {
            vector<bool> num_mask_ = num_mask;
            for (int i=0; i<9; ++i) {
                if (num_mask[i] == true) {
                    num_mask[i] = false;
                    for (const auto& ret_from_recurr : recurr_search(k-1, n-i-1, num_mask)) {
                        vector<int> temp{i+1};
                        temp.insert(temp.end(), ret_from_recurr.begin(), ret_from_recurr.end());
                        ret.emplace_back(temp);
                    }
                    num_mask[i] = true;
                }
                num_mask[i] = false; // mark 1
            }
            num_mask = num_mask_; // mark 2
        }
        
        return ret;
    }
};

Runtime: 4 ms, faster than 35.70% of C++ online submissions for Combination Sum III.
Memory Usage: 7.1 MB, less than 29.37% of C++ online submissions for Combination Sum III.

一开始考虑的是用unordered_set,但是想了想还是用vector<bool>比较方便,set没法O(1) random access。

然后concatenate两个vector一开始不知道,查了一下要用insert
https://stackoverflow.com/a/3177254/9556578

This is precisely what the member function std::vector::insert is for

std::vector<int> AB = A;
AB.insert(AB.end(), B.begin(), B.end());

还有一个小bug,ret.emplace_back(vector<int>{i+1});ret.push_back({i+1});可以通过,但是ret.emplace_back({i+1});不可以
https://stackoverflow.com/questions/51443319/why-is-emplace-back-failing-even-though-the-direct-constructor-works

还有2个问题是关于mask的修改,为了避免重复,必须在mark1的位置要加false,但是这样每次子循环结束都会导致num_mask被完全false掉,导致没有下一个子循环了,所以在mark2的位置要复原成原mask


https://zxi.mytechroad.com/blog/searching/leetcode-216-combination-sum-iii/

其实没必要用mask,搜索的时候因为没有重复,所以可以从上次搜到的数的后一个开始

// Author: Huahua
// Runtime: 0 ms
class Solution {
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> ans;
        vector<int> cur;
        dfs(k, n, 1, cur, ans);
        return ans;
    }
private:
    // Use k numbers (>= s) to sum up to n
    void dfs(int k, int n, int s, 
             vector<int>& cur, vector<vector<int>>& ans) {
        if (k == 0) {
            if (n == 0) ans.push_back(cur);
            return;
        }
        
        for (int i = s; i <= 9; ++i) {
            if (i > n) return;
            cur.push_back(i);
            dfs(k - 1, n - i, i + 1, cur, ans);
            cur.pop_back();
        }
    }
};

我默写的答案:

class Solution {
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> ans;
        vector<int> curr;
        dfs(k, n, 0, curr, ans);
        
        return ans;
    }
    
    void dfs(int k, int n, int start, vector<int>& curr, vector<vector<int>>& ans) {
        if (n < 0) return;
        if (n == 0 and k == 0) {
            ans.emplace_back(curr);
            return;
        }
            
        for (int i=start; i<9; ++i) {
            curr.emplace_back(i+1);
            dfs(k-1, n-i-1, i+1, curr, ans);
            curr.pop_back();
        }
    }
};

Runtime: 0 ms, faster than 100.00% of C++ online submissions for Combination Sum III.
Memory Usage: 6.8 MB, less than 58.74% of C++ online submissions for Combination Sum III.

注意,dfs里面的k n start都不能加引用,因为是k-1, n-i-1, i+1, 0都是rvalue
除非这么写:

class Solution {
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> ans;
        vector<int> curr;
        dfs(k+0, n+0, 0, curr, ans);
        
        return ans;
    }
    
    void dfs(int&& k, int&& n, int&& start, vector<int>& curr, vector<vector<int>>& ans) {
        if (n < 0) return;
        if (n == 0 and k == 0) {
            ans.emplace_back(curr);
            return;
        }
            
        for (int i=start; i<9; ++i) {
            curr.emplace_back(i+1);
            dfs(k-1, n-i-1, i+1, curr, ans);
            curr.pop_back();
        }
    }
};

Runtime: 0 ms, faster than 100.00% of C++ online submissions for Combination Sum III.
Memory Usage: 6.5 MB, less than 91.93% of C++ online submissions for Combination Sum III.

相关文章

  • 2019-01-26

    LeetCode 216. Combination Sum III Description Find all po...

  • 递归与排列组合

    216. Combination Sum III(https://leetcode.com/problems/co...

  • 216. Combination Sum III

    216. Combination Sum III Total Accepted: 38518Total Submi...

  • 216. Combination Sum III (M)

    Combination Sum IIIMedium 1519 61 Add to List ShareFind a...

  • Instantiation of List (Java)

    动机 今天刷Leetcode时碰到的一道问题(216. Combination Sum III): Find al...

  • Leetcode 【216、769】

    题目描述:【DFS】216. Combination Sum III 解题思路: 这道题一看要求输出所有满足题意的...

  • 216. Combination Sum III

    这道题目在微软现场面中遇到了,当年太傻没做出来,其实思路很简单,就是回溯,但是要注意回溯的树的树杈越来越少,代码如下:

  • 216. Combination Sum III

    Find all possible combinations ofknumbers that add up to ...

  • 216. Combination Sum III

    题目 分析 这道题和之前的Combination Sum I II类似,都可以用回溯解法。回溯解法的套路是: ch...

  • 216. Combination Sum III

    找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字...

网友评论

      本文标题:216. Combination Sum III (M)

      本文链接:https://www.haomeiwen.com/subject/szfabktx.html