LeetCode 第17题

17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字。

我最开始是使用了一个回溯函数来解题

class Solution {
public:
    // 定义电话键盘上的字母映射
    const std::string letterMap[10] = {
        "", // 0
        "", // 1
        "abc", // 2
        "def", // 3
        "ghi", // 4
        "jkl", // 5
        "mno", // 6
        "pqrs", // 7
        "tuv", // 8
        "wxyz", // 9
    };
    
    std::vector<std::string> res;
    
    // 函数:生成电话号码的字母组合
    std::vector<std::string> letterCombinations(const std::string& digits) {
        if (!digits.empty()) {
            backtrack(digits, 0, "");
        }
        return res;
    }

private:
    // 回溯函数
    void backtrack(const std::string& digits, int index, std::string path) {
        // 如果当前路径长度等于输入数字长度,表示找到一个有效组合
        if (index == digits.size()) {
            res.push_back(path);
            return;
        }

        // 获取当前数字对应的字母集合
        int num = digits[index] - '0';
        const std::string& letters = letterMap[num];
        
        // 遍历当前数字对应的每个字母
        for (char letter : letters) {
            path.push_back(letter); // 将字母添加到当前路径
            backtrack(digits, index + 1, path); // 递归处理下一个数字
            path.pop_back(); // 回溯,移除当前字母
        }
    }
};

运行时间可以达到最短,但是所需要的内存很大。

在学习了他人的思路后我使用了下面的算法,是一个经典的递归(深度优先搜索,DFS)实现,用于生成电话号码的字母组合。每个数字按电话键盘的映射对应多个字母,代码通过递归逐步构建每个可能的组合。

class Solution {
public:
    // 主函数,负责调用 DFS 并返回结果
    vector<string> letterCombinations(string digits) {
        // 如果输入字符串为空,直接返回空向量
        if (digits.empty()) return {};

        // 构建一个向量数组,每个元素是一个字符向量,对应电话键盘上的字母
        vector<vector<char>> d(10);
        d[0] = {' '};  // 0 键对应空格(通常没有字母,这里设置为一个空格)
        d[1] = {};     // 1 键没有对应的字母
        d[2] = {'a','b','c'};  // 2 键对应 'abc'
        d[3] = {'d','e','f'};  // 3 键对应 'def'
        d[4] = {'g','h','i'};  // 4 键对应 'ghi'
        d[5] = {'j','k','l'};  // 5 键对应 'jkl'
        d[6] = {'m','n','o'};  // 6 键对应 'mno'
        d[7] = {'p','q','r','s'};  // 7 键对应 'pqrs'
        d[8] = {'t','u','v'};  // 8 键对应 'tuv'
        d[9] = {'w','x','y','z'};  // 9 键对应 'wxyz'

        vector<string> ans;  // 存储结果的向量
        string cur = "";     // 当前构建的字符串
        // 调用递归函数开始 DFS
        dfs(digits, d, 0, cur, ans);
        return ans;  // 返回最终结果
    }

private:
    // 递归函数,生成所有可能的字母组合
    void dfs(const string& digits, const vector<vector<char>>& d, int l, string& cur, vector<string>& ans) {
        // 递归终止条件:如果已经处理完所有的数字
        if (l == digits.size()) {
            ans.push_back(cur);  // 将当前构建的字符串添加到结果中
            return;
        }

        // 获取当前数字对应的字母列表
        for (char c: d[digits[l] - '0']) {
            cur.push_back(c);  // 将当前字母添加到当前构建的字符串中
            dfs(digits, d, l + 1, cur, ans);  // 递归处理下一个数字
            cur.pop_back();  // 回溯,移除最后一个添加的字母
        }
    }
};

运行时间稍长但是需要内存极少

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值