电话号码的字母组合

17. 电话号码的字母组合

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

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


电话号码对应图.png
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
输入:digits = ""
输出:[]
输入:digits = "2"
输出:["a","b","c"]

自行解答:

解答1思路:

第一种办法解答和解答3有点类似,但是数据结构用的不太一样。
1:将数字对应的字符填充到map中

2:判断输入数字长度,长度为1,直接将字符填充到result中返回即可,大于1时,就相当于初始化2个vector中的result

3:每次将电话数字对应的char的值分别加上之前temresult中的每一个值 填充到result中去

4:填充完毕一次,先将上一轮积攒的temResult清空,再将result的值同步到temresult中,在进行下一个电话数字字符填充

5:返回result即可,具体代码如下:

vector<string> letterCombinations(string digits) {
    vector<string> result;
    if(digits.length() == 0){
        return result;
    }
        //1:将电话号码数字填充到map中
    map<char,string>allNum;
    allNum.insert(pair<char,string>('2',"abc"));
    allNum.insert(pair<char,string>('3',"def"));
    allNum.insert(pair<char,string>('4',"ghi"));
    allNum.insert(pair<char,string>('5',"jkl"));
    allNum.insert(pair<char,string>('6',"mno"));
    allNum.insert(pair<char,string>('7',"pqrs"));
    allNum.insert(pair<char,string>('8',"tuv"));
    allNum.insert(pair<char,string>('9',"wxyz"));

    char num = NULL;
    string numStr;
        //2:判断长度,如果长度为1,直接将数字对应的char组成string,pusb_back到       //vector中即可返回,若长度大于1,则初始化result
    if(digits.length()>=1){
        num = digits[0];
        numStr = (*allNum.find(num)).second;
        for(int i = 0;i<numStr.length();i++){
            string tem(1,numStr[i]);
            result.push_back(tem);
        }
    }
    if(digits.length()<2){
        return result;
    }
  
  
    vector<string> temResult(result);
    for(int i =1;i<digits.size();i++){
      
        num = digits[i];
        numStr = (*allNum.find(num)).second;
        result.clear();
      //3:每次将电话数字对应的char的值分别加上之前temresult中的每一个值填                            //充到result中去
        for(int j = 0;j<temResult.size();j++){
            string temStr = temResult[j];
            for(int m = 0;m<numStr.size();m++){
                string temStrinner = temStr + numStr[m];
                result.push_back(temStrinner);
            }
        }
      //4:填充完毕一次,先将上一轮积攒的temResult清空,再将result的值同步到          //temresult中,在进行下一个电话数字字符填充
        temResult.clear();
        temResult = result;
    }
    return result;
}
解答2思路:

第二种解法也是官方解法,叫做回溯法,解答点说按题意要求一直找到一个满足题意的要求的解之后,向上返回,从另外的分支继续往下找,寻找下一个可能的值,直到找到所有的解,本质上也是一种暴力法,即穷举所有可能,本题解法有点类似深度优先遍历的意思。

1:将电话号码数字和对应的字符填充到map中

2:递归调用DFS函数,参数为

digits,输入的电话号码数字

index,当前要使用的电话数字在电话号码数字字符中的索引下标

allPhoneNum,电话号码数字和其代表的字符串

result,结果集,存放符合题意的所有字符串

oneResult,符合题意的任意一个解及其这个解的子集

因此函数调用的含义是:将digits字符中的第0个字符对用的所有可能结果填充到result中,每次的变量是index 和oneresult

3:在遍历第0个位置的时候,继续递归调用DFS,此时是将

将digits字符中的第1个字符对用的所有可能结果填充到result中,每次的变量是index 和oneresult,以此递归调用,递归函数退出的basecase 是如果某次index的值是digits 的长度,说明已经走到了最后,此时需要将其中的一个oneresult push_back到result中

4:找到一个符合条件的解之后,向上回溯,即将oneresult 的刚才截掉最后一个字符,在 尝试下一个可能的结

5:递归遍历完成之后所有符合的解全在result中,返回即可

class Solution_1 {
public:
    vector<string> letterCombinations(string digits) {
        vector<string> result;
        if(digits.length() == 0){
            return result;
        }
        //1:将电话号码数字和对应的字符填充到map中
        map<char,string>allNum;
        allNum.insert(pair<char,string>('2',"abc"));
        allNum.insert(pair<char,string>('3',"def"));
        allNum.insert(pair<char,string>('4',"ghi"));
        allNum.insert(pair<char,string>('5',"jkl"));
        allNum.insert(pair<char,string>('6',"mno"));
        allNum.insert(pair<char,string>('7',"pqrs"));
        allNum.insert(pair<char,string>('8',"tuv"));
        allNum.insert(pair<char,string>('9',"wxyz"));

        string oneresult = "";
      //2:递归调用DFS函数
        DFS(digits,0,allNum,result,oneresult);
      //5:递归遍历完成之后所有符合的解全在result中
        return result;
    }

    void DFS(const string &digits,int index,map<char,string> &allPhoneNum,vector<string> &result,string &oneResult ){
        if(index ==digits.size()){
            result.push_back(oneResult);
            return;
        }
        char phoneNUm = digits[index];
        string phoneNUmStr = (*allPhoneNum.find(phoneNUm)).second;
        for(int i = 0;i<phoneNUmStr.size();i++){
            oneResult +=phoneNUmStr[i];
          //3:递归调用DFS函数,参数中index变成了index+1,onesult变成了
          //oneResult +=phoneNUmStr[i]
            DFS(digits,index+1,allPhoneNum,result,oneResult);
          //4:找到一个符合条件的解之后,向上回溯,即将oneresult 的刚才截掉                       //最后一个字符,在 尝试下一个可能的结
            oneResult = oneResult.substr(0,oneResult.size()-1);
        }
    }
};
解答3思路:

解答3其实就是广度遍历,和解答1基本一样,只不过使用queue数据结构实现,更加优美和便于理解

1:将电话号码数字和字符填充到map中

2:调用BFS函数,参数的含义和上面思路2含义一致,只不过将vector换成了queue

3:判断index的值,index的值为digits.size(),即为递归调用的basecase,结束递归调用

4:判断index的值,若为0,直接将字符填充到queue中,继续递归调用自己,index变为index+1

5:若index不是0,且不需要退出,即将queue中的字符从队首拿出,并将队首的字符+index位置对应的字符组成新字符,进行 入队操作,循环此动作,循环的次数是进入此次递归函数时的queue的长度

6:步骤3和步骤4只会执行一个,2个不管哪个执行完成,均继续递归调用BFS,其中indenx变成了index+1,继续执行

7:递归结束之后将quque进行转移到vector中,即可返回

class Solution_2{
public:
    vector<string> letterCombinations(string digits) {
        vector<string> result;
        if(digits.length() == 0){
            return result;
        }
      //1:将电话号码数字和字符填充到map中
        map<char,string>allNum;
        allNum.insert(pair<char,string>('2',"abc"));
        allNum.insert(pair<char,string>('3',"def"));
        allNum.insert(pair<char,string>('4',"ghi"));
        allNum.insert(pair<char,string>('5',"jkl"));
        allNum.insert(pair<char,string>('6',"mno"));
        allNum.insert(pair<char,string>('7',"pqrs"));
        allNum.insert(pair<char,string>('8',"tuv"));
        allNum.insert(pair<char,string>('9',"wxyz"));
        queue<string> tem;
                //2:调用BFS函数,参数的含义和上面思路2含义一致,只不过将vector换成了               //queue
        BFS(0,digits,allNum,tem);
        int  temSize = tem.size();
      //7:递归结束之后将quque进行转移到vector中
        for(int i = 0;i<temSize;i++){
            result.push_back(tem.front());
            tem.pop();
        }
        cout<<"result2:"<<result.size()<<endl;
        return result;
    }

    void BFS(int index,string digits, map<char,string> &phoneMap,queue<string> &temQueue){
      //3:basecase,递归结束条件
        if(index == digits.size()){
            return;
        }
        if(index == 0){
          //4:判断index的值,若为0,直接将字符填充到queue中,继续递归调用自                      //己,index变为index+1
            string firstStr = (*phoneMap.find(digits[index])).second;
            for(int j = 0;j<firstStr.length();j++){
                string oneChar(1,firstStr[j]);
                temQueue.push(oneChar);
            }
        } else{
          //5:若index不是0,且不需要退出,即将queue中的字符从队首拿出,并将              //队首的字符+index位置对应的字符组成新字符,进行 入队操作,循环此动                  //作,循环的次数是进入此次递归函数时的queue的长度
            string tem = temQueue.front() ;
            int currentSize = temQueue.size();
            string indexPhoneNum = (*phoneMap.find(digits[index])).second;
            string temResult;
            for(int i = 0; i <currentSize; i++){
                tem =temQueue.front();
                for(int k=0;k<indexPhoneNum.size();k++){
                    temResult = tem + indexPhoneNum[k];
                    temQueue.push(temResult);
                }
                temQueue.pop();
            }
        }
      //6:步骤3和步骤4只会执行一个,2个不管哪个执行完成,均继续递归调用BFS,      //其中indenx变成了index+1,继续执行
       BFS(index+1,digits,phoneMap,temQueue);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容