03 电话号码的字母组合(leecode 17)

1 问题

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
在这里插入图片描述
示例:
输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].

说明:尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

2 解法

从示例上来说,输入"23",最直接的想法就是两层for循环遍历了吧,正好把组合的情况都输出了。
如果输入"233"呢,那么就三层for循环,如果"2333"呢,就四层for循环…
利用回溯算法解决这种无法囊括所有for循环的问题。
例如:输入:“23”,抽象为树形结构,如图所示:
在这里插入图片描述
图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”]。

回溯三部曲:
(1)确定回溯函数参数
定义全局变量string s记录每个组合的结果,vector res保存全部组合的集合。
函数参数中定义index记录每次遍历digits数组的元素索引,同时index也表示递归层数(树的深度)。

vector<string> res; //存放结果
string s; //存放字母组合
void backtracking(string digits, int index)

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

那么终止条件就是如果index 等于 输入的数字个数(digits.size)。
然后收集结果,结束本层递归。

if (index == digits.size()) {
    
    
    result.push_back(s);
    return;
}

(3)确定单层遍历逻辑

首先要取index指向的数字,并找到对应的字符集(手机键盘的字符集)。

然后for循环来处理这个字符集,代码如下:

   //将字符型数字(2,..9)转换为int
        int num = digits[index] - '0'; 
        //找到数字对应的字母
        string letters = letterMap[num];
        //横向遍历字符串中的字符
        for(int i = 0; i < letters.size(); i++)
        {
    
    
            s.push_back(letters[i]);
            //递归取digits中其它数字对应的字母
            backtracking(digits, index + 1);
            s.pop_back(); //回溯
        }

完整代码如下:

class Solution {
    
    
private:
    const string letterMap[10] = {
    
    
        "", //0
        "", //1
        "abc", //2
        "def", //3
        "ghi", //4
        "jkl", //5
        "mno", //6
        "pqrs", //7
        "tuv", //9
        "wxyz" //10
    };
public:
    vector<string> res; //存放结果
    string s; //存放字母组合
    void backtracking(string digits, int index)
    {
    
    
        //遍历到digits最后一个元素,
        if(index == digits.size())
        {
    
    
            res.push_back(s);
            return;
        }
        //将字符型数字(2,..9)转换为int
        int num = digits[index] - '0'; 
        //找到数字对应的字母
        string letters = letterMap[num];
        //横向遍历字符串中的字符
        for(int i = 0; i < letters.size(); i++)
        {
    
    
            s.push_back(letters[i]);
            //递归取digits中其它数字对应的字母
            backtracking(digits, index + 1);
            s.pop_back(); //回溯
        }
    }
    vector<string> letterCombinations(string digits) {
    
    
        if(digits.size() == 0)
            return res;
        backtracking(digits, 0);
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_42454048/article/details/113849402