【icyle】Leetcode-cn:17. 电话号码的字母组合

题目

解答

思路

map存储key-value组合、dfs回溯解决。

需要的头文件

string、vector、algorithm、unordered_map

代码
/*
 * @lc app=leetcode.cn id=17 lang=cpp
 *
 * [17] 电话号码的字母组合
 */

// @lc code=start
#include <string>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
class Solution
{
public:
    vector<string> letterCombinations(string digits)
    {
        //这里也可以将这三个变量选择放在public处,dfs就不需要引用那么多参数了,但是不安全
        unordered_map<char, string> phonemap = {{'2', "abc"}, {'3', "def"}, {'4', "ghi"}, {'5', "jkl"}, {'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"}};
        //combinations是总的返回答案,one_comb_str是每一次搭配得出的字母组合,pos是对应digits长度的字母组合长度指针
        vector<string> combinations;
        string one_comb_str;
        //特殊情况
        if (digits.empty())
        {
            return combinations;
        }
        NumToLetter_dfs(0, combinations, one_comb_str, phonemap, digits);
        return combinations;
    }

    void NumToLetter_dfs(int pos, vector<string> &combinations, string &one_comb_str, const unordered_map<char, string> &phoneMap, const string &digits)
    {
        //pos等于digits,也就是一次组合完毕后,可以回到上一级
        //比如"23",得出"ad"后返回上一级
        if (pos == digits.size())
        {
            // 将这次的组合词放入combinations中
            combinations.push_back(one_comb_str);
            return;
        }

        //进入正常流程,以下以"23"为例
        else
        {
            //先找到'2',然后从map中找到'2'对应的 "abc"
            string letters = phoneMap.at(digits[pos]);
            //C++11 里面的for的新写法,表示依次取出字符串数组letters中的元素,赋给变量letter
            //对比python的range,是不是感觉很像!
            //分次取出a,b,c
            for (char letter : letters)
            {
                //第一次循环会放入a,之后两次循环就是b和c
                one_comb_str.push_back(letter);
                //回溯,这一步我们可以一次性得到 "ad" "ae" "af",之后请如法炮制
                NumToLetter_dfs(pos + 1, combinations, one_comb_str, phoneMap, digits);
                //如果第一次循环到这了,说明 a 的部分已经检查完了,下一次就到b了
                one_comb_str.pop_back();
            }
            //最后说一下清晰的顺序,第一次正常流程先push'a',然后回溯,检测到长度不够,继续push'd',继续回溯
            //此时检测到长度满足,放入返回数组中,return,跳到最后一句,把'd'pop出来
            //请注意这时候的for循环在第二层(是3对应的 "def"那层,而不是最外层的2对应的 "abc"层)
            //所以下一步循环会放入'e',而不是'b',好好想清楚!
        }
    }
};
// @lc code=end
时间复杂度和空间复杂度(此处复制了官方解释,准确到位。)
  • 时间复杂度: O(3m * 4n ) ,其中 m 是输入中对应 3 个字母的数字个数(包括数字 2、3、4、5、6、8),n 是输入中对应 4 个字母的数字个数(包括数字 7、9),m+n 是输入数字的总个数。当输入包含 m 个对应 3 个字母的数字和 n 个对应 4 个字母的数字时,不同的字母组合一共有3n * 4m种,需要遍历每一种字母组合。

  • 空间复杂度:O(m+n) ,其中 m 是输入中对应 3 个字母的数字个数,n 是输入中对应 4 个字母的数字个数,m+n是输入数字的总个数。除了返回值以外,空间复杂度主要取决于哈希表以及回溯过程中的递归调用层数,哈希表的大小与输入无关,可以看成常数,递归调用层数最大为 m+n。

反思与总结

dfs经典用法,需要牢记。另外要多接触 for (char letter : letters) 这种新写法,C++11的新特性,类比python的range

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值