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 处理下一个数字,递归回来后撤销当前选择。

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

相关推荐
维克兜率天2 分钟前
【维克】均值回归:跌多了会涨,涨多了会跌
开发语言·笔记·python·算法·均值算法·回归·量化
yi01115 分钟前
DAY 14: LeetCode 394. 字符串解码|递归和栈到底怎么处理嵌套?
数据结构·笔记·python·算法·leetcode
P.D.Wei39 分钟前
[Leetcode 1614] 括号的最大嵌套深度
算法·leetcode·职场和发展
红姐跨境书1 小时前
AI 的底层逻辑:从数据、算法到智能的本质
人工智能·算法
繁华的地方不一定留下你的脚印1 小时前
C++ 算法与 ranges:用 find_if、transform 写清数据处理意图
开发语言·c++·算法
青山是哪个青山1 小时前
LeetCode 64:最小路径和
算法
blxr_1 小时前
力扣hot100寻找重复数https://leetcode.cn/problems/find-the-duplicate-number/
算法·leetcode·职场和发展
政企项目老覃1 小时前
金融医疗数据脱敏与隐私计算:从字段打码到联邦建模的落地复盘
程序人生·算法·金融·数据分析
❀͜͡傀儡师2 小时前
Spring Boot 实现图片盲水印:基于 DCT 频域算法的隐形数字水印
spring boot·算法
Zane19942 小时前
贪心算法大多靠不住,为什么Dijkstra的贪心选择偏偏能保证全局最优
算法