LeetCode 216. Combination Sum III 解题报告

LeetCode 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.


示例

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


限制条件

没有明确给出.


解题思路

我的思路:

这道题很明显就是用回溯的思想,而对于回溯,我印象最深的就是N皇后问题,所以在解题时,我不自觉地就套用了N皇后问题的解题框架,N皇后问题请参考LeetCode 52. N-Queens II 解题报告

首先说一下预设的一些变量:
用一个大小为k的数组sol存储找到的结果,以及用一个布尔变量isBack标志我们是否在回溯。

整个过程是在一个循环里进行,遍历数组sol的每一位,处理过程分为3大块:

1.给sol[i]赋值,赋值的规则是对于非最后一位,如果我们不是在回溯,那么sol[i] = sol[i - 1] + 1,如果在回溯,那么sol[i] = sol[i] + 1,对于最后一位,sol[i]等于n减去前面所有位后的值。最后当sol[i] > 9就得把sol[i]设为0表示没有合适的值。这样设置的原因是题目限制了只能用1-9的数字且只能用1次,所以我们找结果的时候,就可以默认sol中后一位至少比前一位大1,并且大于9的值是无效的。

2.在sol[i]等于0的前提下,如果当前位是第0位,就表明我们已经找到所有了结果,所以可以跳出循环,返回找到的所有结果。如果不是第0位,那么就回溯到上一位。

3.如果sol的最后一位也找到了合适的数值,就代表着找到了一种组合,所以添加到结果集中,然后我们也回溯到上一位去寻找新的组合。

结合着下面我的代码,会发现这整个过程其实是一个很浅显直接的解法。

其他思路:

在Discuss里,有大牛给出了递归方式的解法,核心的思想就是通过递归给结果数组的每一位赋值,并且通过一个循环尝试赋予从1到9的每一个值,其中赋值时,如果是首位就是从1开始尝试,如果是其他位就从前一位大1的数开始尝试。见下面的其他代码。


代码

我的代码

class Solution {
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> result;
        vector<int> sol(k, 0);
        int i = 1;
        bool isBack = false;
        int remain = n - 1;

        sol[0] = 1;
        while (i < k) {
            if (i != k - 1) {
                sol[i] = isBack? sol[i] + 1: sol[i - 1] + 1;
                if (sol[i] <= 9)
                    remain -= sol[i];
                else
                    sol[i] = 0;
                isBack = false;
            } else {
                if (remain <= 9 && remain > sol[i - 1])
                    sol[i] = remain;
                else
                    sol[i] = 0;
            }

            if (!sol[i]) {
                if (!i)
                    break;
                else {
                    isBack = true;
                    remain += sol[--i];
                    continue;
                }
            }

            if (i == k - 1) {
                result.push_back(sol);
                isBack = true;
                remain += sol[--i];
                continue;
            }

            i++;
        }

        return result;
    }
};

其他代码

class Solution {
public:
    void combination(vector<vector<int>>& res, vector<int> sol, int k, int n) {
        if (sol.size() == k && n == 0)
            res.push_back(sol);

        for (int i = sol.empty()? 1 : sol.back() + 1; i <= 9; i++) {
            if (n - i < 0)
                break;
            sol.push_back(i);
            combination(res, sol, k, n - i);
            sol.pop_back();
        }
    }

    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> res;
        vector<int> sol;

        combination(res, sol, k, n);

        return res;
    }
};

总结

这道题也不算很难,有了一个思路之后慢慢调整自己的实现就能做出来,递归方式的求解显得很精简,有值得我去学习的地方。
轻松地填了这个坑,这是目前最后一个通过率在40%以上的题目,之后的题目开始更有难度了,要加把劲了!努力努力~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值