LeetCode刷题笔记—17.电话号码的字母组合

No17:电话号码的字母组合

题目

LeetCode17

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

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

输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].

思路

没什么好说的,直接dfs即可,需要注意的是,这里对数字的顺序不做要求,即:“ab” 和 “ba” 是同一个答案,因此我们不需要使用 hasUsed 标识路径,直接使用 index 索引完成顺序遍历数字字符串即可,那么提供原版代码和改进时间性能的代码。

代码

原版代码:使用Map存储对应关系,用 StringBuffer 存储组装结果,在dfs过程中在每个对应的 index 索引位置上取出其中一个字符组装结果并进入递归,在递归结束后再删除这个字符,接着取出下一个字符组装结果,直到该数字对应的字符都被遍历完。

public class Solution {
    public List<String> letterCombinations(String digits) {
        List<String> combinations = new ArrayList<>();
        if(digits.length()==0)
            return combinations;
        Map<Character,String> phoneMap = new HashMap<>();
        //
        phoneMap.put('2',"abc");
        phoneMap.put('3',"def");
        phoneMap.put('4',"ghi");
        phoneMap.put('5',"jkl");
        phoneMap.put('6',"mno");
        phoneMap.put('7',"pqrs");
        phoneMap.put('8',"tuv");
        phoneMap.put('9',"wxyz");
        //不同顺序相同字符集合也是同一个答案,因此从索引为0开始递归调用,
        //因为不要求字典序,所以从index=0开始,一定可以遍历到index=n-1
        bactrack(combinations,phoneMap,digits,0,new StringBuffer());
        return combinations;
    }

    //递归函数,控制参数其实也就只有 int index 和 StringBuffer combination
    private void bactrack(List<String> combinations,Map<Character,String> phoneMap,
                          String digits,int index,StringBuffer combination){
        //递归终止条件
        if(index==digits.length())
            combinations.add(combination.toString());
        else{
            //取出index所在的数字
            char digit = digits.charAt(index);
            //得到该数字对应的字符
            String letters = phoneMap.get(digit);
            int lettersCount = letters.length();
            //从字符起始处开始遍历
            for(int i=0;i<lettersCount;i++){
                //加入字符
                combination.append(letters.charAt(i));
                //递归,index+1,找到下一个数字对应的字符
                bactrack(combinations,phoneMap,digits,index+1,combination);
                //回退,删除该字符,等待另外的循环里将其他字符放在此处
                combination.deleteCharAt(index);
            }
        }
    }

性能提升:用数组替换HashMap,使用char[] 存储组装结果,比起 StringBuffer ,字符数组不需要回退,因为索引相同的字符最终都会覆盖旧值。

public class Solution {
    private char[][] lettersArray = {
            {'a','b','c'},{'d','e','f'},{'g','h','i'},
            {'j','k','l'},{'m','n','o'},{'p','q','r','s'},
            {'t','u','v'},{'w','x','y','z'}
    };
//    方法2:运行速度快:dfs的每次循环中由于不需要进行回退操作,因此提升了速度
//    巧妙地使用了char[]来进行处理,不需要考虑回退的问题,因为每次写入新值都会覆盖掉旧值
    public List<String> letterCombinations2(String digits) {
        List<String> ret = new ArrayList<>();
        if(digits==null||digits.length()==0)
            return ret;
        char[] chars = digits.toCharArray();
        dfs(chars,new char[chars.length],0,ret);
        return ret;
    }

    private void dfs(char[] chars,char[] result,int index,List<String> ret){
        if(index==chars.length){
            ret.add(new String(result));
            return;
        }
//        因为这里使用的是char[]数组的形式组成答案,因此不需要回退,每次for循环会自动覆盖该位置对应的值
        char[] letters = lettersArray[chars[index] -'2'];
        for (int i = 0; i < letters.length; i++) {
            result[index] = letters[i];
            dfs(chars,result,index+1,ret);
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值