leetcode 17电话号码的字母组合

可以,这道"电话号码的字母组合"就按你刚才喜欢的那种方式总结。

复制代码
class Solution {
public:
    vector<string> res;  // 保存所有字母组合

    vector<string> letternumber = {
        "", "", "abc", "def", "ghi",
        "jkl", "mno", "pqrs", "tuv", "wxyz"
    };

    vector<string> letterCombinations(string digits) {
        string tmp;  // 当前正在构造的字符串

        backtracing(0, digits, tmp);

        return res;
    }

    void backtracing(int pos, string digits, string& tmp) {

        // 所有数字都已经处理完,得到一个完整组合
        if (pos == digits.length()) {
            res.push_back(tmp);
            return;
        }

        // 取出当前数字
        int num = digits[pos] - '0';

        // 遍历当前数字对应的所有字母
        for (int i = 0; i < letternumber[num].size(); i++) {

            // 做选择
            tmp.push_back(letternumber[num][i]);

            // 进入下一层,处理下一个数字
            backtracing(pos + 1, digits, tmp);

            // 回溯:撤销刚才选择的字母
            tmp.pop_back();
        }
    }
};

这题可以按照你刚才说的"回溯参数五件套"来分析。

复制代码
原始数据:digits
当前路径:tmp
当前位置:pos
额外状态:不需要
结果集:res

所以回溯函数就是:

复制代码
void backtracing(int pos, string digits, string& tmp)

其中最重要的三个东西:

复制代码
pos

表示当前正在处理:

复制代码
digits[pos]

例如:

复制代码
digits = "23"

pos = 0 → 处理数字 2
pos = 1 → 处理数字 3
pos = 2 → 全部处理完成

复制代码
tmp

表示当前已经选择出来的字母组合。

例如:

复制代码
""
"a"
"ad"

每次:

复制代码
tmp.push_back(...)

就是选择当前数字对应的一个字母。

每次:

复制代码
tmp.pop_back()

就是撤销选择。


复制代码
letternumber

负责建立:

复制代码
数字 → 字母

的映射。

例如:

复制代码
2 → abc
3 → def
7 → pqrs
9 → wxyz

所以:

复制代码
int num = digits[pos] - '0';

先把字符 '2' 转成整数 2。

然后:

复制代码
letternumber[num]

就可以得到:

复制代码
"abc"

这题最核心的三步依然是:

复制代码
tmp.push_back(letternumber[num][i]);  // 做选择

backtracing(pos + 1, digits, tmp);    // 进入下一层

tmp.pop_back();                       // 撤销选择

也就是:

做选择 → 递归下一层 → 撤销选择

比如:

复制代码
digits = "23"

递归过程:

复制代码
                 ""
              处理数字2
          /       |       \
         a        b        c
       处理3    处理3    处理3
      / | \      ...      ...
     d  e  f

得到:
ad
ae
af
bd
be
bf
cd
ce
cf

这道题和你前面做过的题还有一个很重要的区别:

全排列是:

每一层从"所有没有使用过的数字"中选择。

所以需要:

复制代码
used

子集是:

每一层从 index 后面的数字中选择。

所以需要:

复制代码
index

而电话号码组合是:

第 pos 层只能处理 digits[pos] 对应的字母。

所以这里需要的是:

复制代码
pos

一句话总结这道题:

每一层递归处理一个数字,从该数字对应的字母中选择一个加入 tmp,然后 pos+1 处理下一个数字,递归回来后撤销当前选择。

你以后看到这种"每个位置都有若干种选择,要求组合出所有结果"的题,就可以优先想到这种回溯结构。

相关推荐
I_belong_to_jesus9 小时前
C++关于分支预测的优化1
开发语言·c++·算法
Code_Solitude16 小时前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组
上海潭龙东海科技有限公司16 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
文丑颜不良啊17 小时前
LeetCode2821~2840题目解析
java·leetcode
YLCHUP19 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
思麟呀19 小时前
背包DP(01背包+完全背包)
c++·算法
笑容掩饰我的失落20 小时前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法
Pniubi21 小时前
力扣24. 两两交换链表中的节点(递归)
算法·leetcode·链表
꧁细听勿语情꧂1 天前
直接选择排序,堆排序,冒泡排序,递归快速排序、hoare版本、挖坑法、lomuto前后指针,非递归快速排序
c语言·开发语言·数据结构·算法