[leetcode]17. Letter Combinations of a Phone Number

17. Letter Combinations of a Phone Number

Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.

A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.

Example:

Input: "23"
Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

Note:

Although the above answer is in lexicographical order, your answer could be in any order you want.

 

这个题目看起来真的不难,很显然,我们可以对应地列出一个数组与对应字符串的关系,就类似于python的字典,2与"abc"是对应的,然后逐个字符检查输入的字符串,这样能把其对应的字符串取出来,放进一个列表里面。

然而我一开始想到这里的时候,就觉得这样的话,写一个N次的循环就可以了啊。。例如有列表里面有3个字符串,可以用一个3层的for循环,第一层拿一个,然后第二层拿一个,第三层去遍历这样子。。后面想了想。。3个的时候还好,如果是N个呢。。那要写N个for循环也太难受了吧。。。况且N是未知的。加上这一题,确实是有一个很明显的递归关系,假设我们最终取的字符串长度是N,我们可以这样看,第一个字符从第一个字符串里面取,剩下N-1个字符就从剩下N-1个个字符串里面取。怎么取出长度为N-1的字符串呢,那么同样的,也是在这N-1个字符串里面,从第一个字符串里面取一个,剩下的从N-2个去取。。。这就形成了一个递归的过程。直到没有字符串就可以停止了。

java代码如下:

class Solution {
    public List letterCombinations(String digits) {
        String[] number_to_string = { "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
        List quest_list = new ArrayList();
        List answer_list = new ArrayList();
        
        //这个提交的时候吃过一次亏。。加上这句是可以处理空字符串的情况的
        if(digits.length() == 0)
            return answer_list;
        
        //构造问题字符串
        for(int i = 0;i < digits.length();i++){
            for(int j = 0;j < 8;j++){
                int temp = digits.charAt(i) - 48;
                if(temp == j + 2){
                    quest_list.add(number_to_string[j]);
                }
            }
        }
        //调用递归
        recursive(quest_list,answer_list,0,quest_list.size(),"");
        return answer_list;
    }
    
    //递归函数
    public void recursive(Listquest_list,Listanswer_list,int n,int length,String s){
        //如果字符串列表已经查找完,就把s字符串添加进答案列表
        if(n == length){
            answer_list.add(s);
            return;
        }

        //遍历所有字符串列表
        for(int i = 0;i < quest_list.get(n).length();i++){
            //把上次的字符串记录下来
            String s1 = new String(s);
            
            //添加当前字符
            s1 += quest_list.get(n).charAt(i);
            
            //递归
            recursive(quest_list,answer_list,n + 1,length,s1);
        }
        return;
    }
}

emm值得注意的是,在recursive的for循环里面,每次都应该把上一层的字符串复制下来。举个例子,假设是例题所示的”23“,”23“分别对应的是”abc","def",第一个得出的结果字符串肯定是“ad",如果我们是直接用s += quest_list.get(n).charAt(i),那么由于上次递归结束了,for会继续执行s+ = quest_list.get(n).charAt(i),此时i = 1,也就是对应的字符是e,由于s = "ad",s += 'e'就会得出s = "ade"。。后面s就会越来越长。解决的方法就是,我们在for循环的每次执行,都把s复制一次,这样我们在for循环里面就不会对s的值发生改变,例如上面这个例子,i = 1的时候,由于我们改变的是s1,不是s,s 依然是等于"a"。递归的参数也由s换成了s1,由于递归是向下一层展开的,所以s1作为了下一层的s参数。

这样的递归就符合了我们一开始讲的思路,s会记录当前这一层的字符串,然后一层一层往下扩展,找到了终点就结束,把答案加入答案列表里面。emm可惜我没有一些工具画图。。画个图就会很好理解了,我也不知道这算不算是一种基本dfs算法。。毕竟大二acm和算法学的知识忘了很多了23333。。。

递归很久没用确实有点生疏了,不过这个题目的递归过程确实相对简单,也不算它困难就通过了。

你可能感兴趣的:(leetcode)