第四周第六天|力扣216、组合总和III 17、电话号码的字母组合

力扣216、组合总和III

思路:组合总和和上一道题组合有着很多相似的地方,比如说,它们都要求是k个数的组合,再比如它们都是在一个给定的范围内选取元素,只不过这道题目多了一个总和的限制,这一点可以通过增设参数来解决。

首先我们需要定义一个结果集,还需要定义一个二维数组用来保存结果集,接着我们需要确定回溯函数的返回值及参数,返回值我们说过了,没有特殊情况都是void,至于参数,题目所要求的总和肯定要有吧,我给他命名为targetSum,其次还需要k用来表示组合的个数要求,范围是给定的,此外为了方便比较当前结果集中的总和和目标值的差距,我们设置一个sum表示当前和,再设置一个index用来记录下一次使用搜索开始的位置。

接下来我们要做的就是确定终止条件了,一般情况下,当我们把回溯问题转换成N叉树后,当我们碰到叶子节点时,就是递归的终止了,在这里就是当我们结果集中的元素个数已经等于组合个数的要求k时,就去比较结果集中的sum和目标值的差距,如果二者相等,我们就保存结果到二维数组中,否则直接return

最后就是单层递归的逻辑了,我们用for循环来进行横向遍历,用递归来进行纵向遍历,for循环来遍历给定的范围,也就构成了树的宽度,递归的深度则由k决定,递归后要通过回溯来撤销之前运行的痕迹,这样代码的逻辑大致就写完了。

代码:

class Solution {
public:
    vector<vector<int>>result;
    vector<int>path;
    //targetSum是目标和
    //sum是已经球的的和
    //startIndex记录下层遍历开始的搜索位置
    void backtracking(int targetSum,int k,int sum,int startIndex){
        if(path.size()==k){
            if(sum==targetSum)result.push_back(path);
            return;
        }
        for(int i=startIndex;i<=9;i++){
            sum+=i;
            path.push_back(i);
            backtracking(targetSum, k, sum, i+1);//i+1调整下层搜索的起始位置
            sum-=i;
            path.pop_back();
        }
    }
    vector<vector<int>> combinationSum3(int k, int n) {
        result.clear();
        path.clear();
        backtracking(n, k, 0, 1);
        return result;
    }
};

17、电话号码的字母组合

思路:本题同样是一道组合类型的问题,但是和上一题不同,对于本题而言,结果集的长度由输入的字符串的长度决定,结果集的每一位字符由字符串对应位置的字符所对应的数字确定。

首先还是要先定义两个全局变量,一个定义成字符串用来保存符合条件的字母组合,一个定义成字符串数组用来保存所有符合条件的字母组合。然后就是回溯第一步了,返回值还是void,参数的话题目所给的字符串我们肯定需要呀,为了保证安全,我们可以给它加上一个const,接着我们还要再添加一个int型变量index,用来告诉我们下一次搜索的字符位置。

接着就是递归的中止条件,把本题转化成N叉树,那么当我们碰到叶子节点的时候,也就是我们的字符串的大小和输入的字符串的大小长度相同的时候,我们就保存结果,return即可。(这里用index做判断也可以)

最后是单层递归逻辑,我们用for循环来把当前数字所对应的字符集给加入字符串,用递归来实现长度符合题目要求的结果集字符串,用回溯来撤销之前的痕迹重新递归。

补充说明:这里应该如何处理一个数字所对应的字母集呢?我们可以定义一个二维数组来实现。

代码:

class Solution {
public:
    vector<string>result;
    string s;
    //定义一个二维数组用来保存字符集
    const string stringMap[10]={
        "",//0
        "",//1
        "abc",//2
        "def",//3
        "ghi",//4
        "jkl",//5
        "mno",//6
        "pqrs",//7
        "tuv",//8
        "wxyz",//9
    };
    void backtracking(const string&digits,int startIndex){
        //注意这里的startindex和组合里面的作用不同,这里的startindex是用来记录下一个要处理的数字
        //字符串的长度决定了树的深度,每一个字符所对应的键盘上的数字决定了树的宽度
        if(s.size()==digits.size()){
            result.push_back(s);
            return;
        }
        int digit=digits[startIndex]-'0';//将startindex转换成整型
        string stringLetter=stringMap[digit];
        for(int i=0;i<stringLetter.size();i++){//这里第二个循环条件很细节,i小于字符集的长度
            s.push_back(stringLetter[i]);
            backtracking(digits, startIndex+1);//递归
            s.pop_back();//回溯
        }
    }
    vector<string> letterCombinations(string digits) {
        result.clear();
        s.clear();
        if(digits.size()==0){
            return result;
        }
        backtracking(digits, 0);
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值