Leetcode[字符串] 17. 电话号码的字母组合

Leetcode[字符串] 17. 电话号码的字母组合


递归

审题

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

这道题最开始看的时候真的是一点想法都没有…因为如果想要遍历的话能想到的就是循环,然而循环的次数是由用户输入的字符串长度决定的,那么应该怎么办呢,于是,我尝试去使用递归的思路,也就是说,如果对应的字符串为1,显然就是数字对应的几个字母即为解答,而当大于1的时候,直接将前面的字符串和最后一位数字组合就可以了,而前面的字符串的可能怎么算呢?依旧是拆成x-1长度的字符串和长度为1的字符串组合,以此类推。

代码实现

方案一(上文提到的方法):

class Solution {
public:
    vector<string> cat(vector<string> v1, vector<string> v2) {
        vector<string> new_vec;
        for ( int i=0; i<v1.size(); i++ ) {
            for ( int j=0; j<v2.size(); j++ ) {
                new_vec.push_back(v1[i]+v2[j]);
            }
        }
        return new_vec;
    }
    vector<string> test(string s) {
        string front = "";
        string end = "";
        vector<string> v;
        if ( s.size() == 1 ) {
            switch (s[0]) {
                case '2': 
                v.push_back("a"); v.push_back("b"); v.push_back("c");
                break;
                case '3': 
                v.push_back("d"); v.push_back("e"); v.push_back("f");
                break;
                case '4': 
                v.push_back("g"); v.push_back("h"); v.push_back("i");
                break;
                case '5': 
                v.push_back("j"); v.push_back("k"); v.push_back("l");
                break;
                case '6': 
                v.push_back("m"); v.push_back("n"); v.push_back("o");
                break;
                case '7': 
                v.push_back("p"); v.push_back("q"); v.push_back("r"); v.push_back("s");
                break;
                case '8': 
                v.push_back("t"); v.push_back("u"); v.push_back("v");
                break;
                case '9': 
                v.push_back("w"); v.push_back("x"); v.push_back("y"); v.push_back("z");
                break;
            }
        } else {
            for ( int i=0; i<s.size(); i++ ) {
                if ( i!=s.size()-1 ) {
                    front += s[i];
                } else {
                    end += s[i];
                }
            }
            if ( end.size() == 1 ) {
                v = cat(test(front), test(end));
            }
        }
        return v;
    }

    vector<string> letterCombinations(string digits) {
         return test(digits);
    }
};

方案2:
这个方法是看到题解学到的,将每个字母视作一个节点,可以想象成一个三叉树,进行后根序列遍历(只是概念相似,不太严谨,官方题解好像把这个叫做回溯法),只用一个for循环进行一个字符串中的三或四个字母遍历就可以了,可以说,DFS的层次深度-1就是在外面再套几次循环,是一种通用的方法,需要熟练掌握。

class Solution {
public:
    string tmp;
    int len;
    vector<string> res;
    vector<string> board = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

    void dfs(string s, int pos) {
        if ( pos==s.size() ) {
            res.push_back(tmp);
            return;
        } else {
            for ( int i=0; i<board[s[pos]-'0'].size(); i++ ) {
                tmp.push_back(board[s[pos]-'0'][i]);
                dfs(s,pos+1);
                tmp.pop_back();
            }
        }
    }

    vector<string> letterCombinations(string digits) {
        if ( digits.size() == 0 ) return res;
        dfs(digits,0);
        return res;
    }
};

反思

做了几道字符串的题,感觉是和很多内容都可以相关联起来的,因此,单独刷字符串在碰到陌生的知识的时候可能会学的比较累,然而,这也是快速增加知识广度的好方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值