第二十八天 | 216.组合总数||| 17.电话号码的字母组合

回溯法抽象为树形结构后,其遍历过程就是:for循环横向遍历,递归纵向遍历,回溯不断调整结果集

题目:216.组合总数|||

会了77.组合,这道题是轻而易举了。

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(int n, int k, int startIndex){
        if(path.size() == k){
            if(n == 0){
                result.push_back(path);
                return;
            }
        }

        for(int i = startIndex; i <= 9; i++){
            n -= i;
            path.push_back(i);
            backtracking(n, k, i + 1);
            n += i;
            path.pop_back();
        }
    }
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        backtracking(n, k, 1);
        return result;
    }
};

题目:17.电话号码的字母组合

尝试解答:

class Solution {
private:
    string path;
    vector<string> result;
    void backtracking(string digits, int startIndex){
        if(string.size() == digits.size()){
            result.push_back(path);
        }

        for(int i = startIndex; i < digits.size(); i++){
            string.push()
        }
    }
public:
    vector<string> letterCombinations(string digits) {
        backtracking(digits, 0)
    }
};

代码打到这里,就意识到本题与之前组合那道题的不同点在哪里了。即在递归的过程中for循环遍历的集合是不一样的,最高层遍历的集合为digits,而往下一层for循环遍历的集合时每一个digits中的元素对应的字母,例如:1->abc。

这应该怎么解决呢?

解决方法:映射

        可以用map来做映射,也可以用二维数组来做映射

本体思路:

        1.深度:输入字符串的长度

        2.宽度:每一个数组所映射的字母的个数

        3.参数:index:用于标记遍历到了第几个元素(不需要用startIndex做去重的操作)

        4.终止条件:index == digits.size().index索引到digits最后一个元素的下一个元素。

例如输入用例"23",两个数字,那么根节点往下递归两层就可以了,叶子节点就是要收集的结果集。

那么终止条件就是如果index 等于 输入的数字个数(digits.size)了(本来index就是用来遍历digits的)。

然后收集结果,结束本层递归。

        5.可进行回溯隐藏:将回溯过程隐藏在参数里

        

自己写代码时会有的困难:

        1.怎样想到用二维数组做映射?

        2.二维数组应该如何定义?

        3.怎样将index所指向的数字字符映射到字母字符串,进而将该字符串作为本层for循环的范围?

        4.需要加强对index这个参数的理解:index标记遍历到了digits的哪一个元素。

        5.为什么如果不在主函数中对digits.size() == 0的情况单独讨论,答案就会错?

class Solution {
private:
    const string letterMap[10] = {
        "", //0
        "", //1
        "abc", //2
        "def", //3
        "ghi", //4
        "jkl", //5
        "mno", //6
        "pqrs", //7
        "tuv", //8
        "wxyz",//9
    };
public:
    vector<string> result;
    string path;
    void backtracking(string digits, int index){
        if(index == digits.size()){
            result.push_back(path);
            return;
        }

        int digit = digits[index] - '0';     //将index指向的数字转化为int
        string letter = letterMap[digit];    //成功将数字字符映射到它对应的字母字符串
        for(int i = 0; i < letter.size(); i++){
            path.push_back(letter[i]);
            backtracking(digits, index + 1);
            path.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
        path.clear();
        result.clear();
        if(digits.size() == 0){
            return result;
        }            //为什么这个if判断不能省略?
        backtracking(digits, 0);
        return result;
    }
};

本题每一个数字代表的是不同集合,也就是求不同集合之间的组合,而77. 组合 (opens new window)216.组合总和III (opens new window)都是求同一个集合中的组合。本题是多个集合求组合,所以在回溯的搜索过程中,都有一些细节需要注意的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值