代码随想录算法训练营Day24| 77. 组合 , 216.组合总和III , 17.电话号码的字母组合

77. 组合:代码随想录

这道题目的意思就是让你返回从一到n中所有可能的k个数的组合,这道题我们采用的是回溯的方法,首先,回溯最重要的就是递归的部分,递归函数的参数以及返回值,还有递归的终止条件,以及单层递归的逻辑,首先定义两个动态数组,然后就是传入的参数为n,k,还有控制下标的startindex,因为不能出现重复的情况,所以要控制下标,然后就是终止条件,当我数组的长度等于k的值时,这个时候代表我要将该数组加入到我的结果数组中,否则的话我就for循环,这里的for循环相当于那个递归树的宽度,而递归函数的嵌套调用就相当于我递归树的深度,然后在for循环里面依然是int i=startindex,这样递归的传入stratindex才能保证我一直是在找后面的数,这样就不会重复,然后就是pushback元素,接着递归调用,然后递归调用结束后将元素弹出,最后返回result数组即可。

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    vector<vector<int>> combine(int n, int k) {
        backtracking(n, k, 1);
        return result;
    }
    void backtracking(int n, int k, int startindex) {
        if (path.size() == k) {
            result.push_back(path);
            return;
        }
        for (int i = startindex; i <= n; i++) {
            path.push_back(i);
            backtracking(n, k, i + 1);
            path.pop_back();
        }
    }
};

注意这里的剪枝优化操作,因为如果我的k等于2,而此时已经遍历到我的数组的最后一位了,那其实就没有必要再去遍历了,因为后面的元素个数都没有k个,所以我们这里可以得出一个式子——k-path.size()代表我还需要加入多少元素,而n-(i-1)代表我还剩下多少个元素没有遍历,只有前面的式子小于等于我我后面的式子时,才有结果,否则,就不需要再继续遍历了。

216.组合总和III:代码随想录

这道题目其实和上一道题目一样,只不过是加了一些约束条件,直接来看代码

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

当我数组里的元素个数等于我的k并且我的元素数值的总和等于我的n时,就代表此时我要收集我的结果集,,否则的话,我就要进入for循环,这里和上面一样,只不过是加了一个参数sum

17.电话号码的字母组合:代码随想录

这道题目其实也是一样,直接看代码

class Solution {
public:
    vector<string> result;
    string ans="";
    string d[10] = { "","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz" };
    vector<string> letterCombinations(string digits) {
        if(digits.size()==0) return result;
        backtracking(0, digits.size(), digits);
        return result;
    }
    void backtracking(int index,int size,string s) {
        if (ans.size() == size) {
            result.push_back(ans);
            return;
        }
        for (int i = index; i < size; i++) {
            int a = s[i] - '0';
            a--;
            string t = d[a];
            for (int j = 0; j < t.size(); j++) {
                string ans1 = ans;
                ans += d[a][j];
                backtracking(i + 1, size, s);
                ans = ans1;
            }
        }
    }
};

同样的当元素个数达到传入字符串的大小时,返回结果,这里最主要的不同是有两个for循环,但其实都是一样的,只不过是树的宽度变宽了而已。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值