leetcode之回溯backtracing专题3

17 Letter Combinations of a Phone Number

 手机上每个数字按钮旁边都有3-4个字母,输入数字字符串,输出可能的字母组合。
 例如输入:”23”
 输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
 思路:建立每个数字和对应字母的映射关系。该个处理每一位数字,遍历每个数字可能的取值。按照递归去实现很简单。
 

private  List<String> result = new ArrayList<String>();
private static Map<Integer, List<Character>> numberMap = new HashMap<Integer, List<Character>>();
static{
    for(int i=2;i<7;i++){
        numberMap.put(i, new ArrayList<Character>());
        for (int j = 0; j < 3; j++) {
            char ch = (char) ('a' + 3 * (i - 2) + j);
            numberMap.get(i).add(ch);
        }

    }
    numberMap.put(7, new ArrayList<Character>());
    numberMap.get(7).add('p');
    numberMap.get(7).add('q');
    numberMap.get(7).add('r');
    numberMap.get(7).add('s');
    numberMap.put(8, new ArrayList<Character>());
    numberMap.get(8).add('t');
    numberMap.get(8).add('u');
    numberMap.get(8).add('v');
    numberMap.put(9, new ArrayList<Character>());
    numberMap.get(9).add('w');
    numberMap.get(9).add('x');
    numberMap.get(9).add('y');
    numberMap.get(9).add('z');

}
public List<String> letterCombinations(String digits) {
    result.clear();
    StringBuilder str = new StringBuilder(digits.length());
    str.setLength(digits.length());
    if(digits.length()>0){
        robot(0, digits, str);
    }
    return result;
}



private void robot(int idx, String digits, StringBuilder r) {
    if (idx >= digits.length()) {
        result.add(r.toString());
        return;
    }
    int n = digits.charAt(idx) - 48;
    if (n < 2)
        return;
    for(char ch : numberMap.get(n)){
        r.setCharAt(idx, ch);
        robot(idx + 1, digits, r);
    }
}

收获1

 嗯代码够丑的。看别人怎么处理映射关系。我怎么没想到呢。之前也有这样一个例子,当数字作为map的key的时候,选择用数组代替map,可能会是一种比较优雅的方式。
 

String[] mapping = new String[] {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

收获2

 一次性给stringBuider 一定的长度。这个做法在字符串中还是有点变扭。这个想法是从数组那里继承过来的。可以使用字符串相加的方式。
 

private static final String[] KEYS = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
private List<String> result = new ArrayList<String>();

public List<String> letterCombinations(String digits) {
    result.clear();
    robot(0, digits, "");
    return result;
}

private void robot(int idx, String digits, String prefix) {
    if (idx >= digits.length()) {
        if (prefix.length() > 0) {
            result.add(prefix);
        }

        return;
    }
    int n = digits.charAt(idx) - 48;
    if (n < 2)
        return;
    String letters = KEYS[n];
    for (int i = 0; i < letters.length(); i++) {
        robot(idx + 1, digits, prefix + letters.charAt(i));
    }
}

收获3

 我是没法用递推的方式实现的,只能用递归。看看别人怎么做。其实从上一个递归的代码是可以得到一些启示的。当然这是“马后炮”的想法–看到别人这么做觉得应该想到的。但是之前我一直在用for去思考。
 

public List<String> letterCombinations(String digits) {
        LinkedList<String> ans = new LinkedList<String>();
        String[] mapping = new String[] { "0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
        ans.add("");
        for (int i = 0; i < digits.length(); i++) {
            int x = Character.getNumericValue(digits.charAt(i));
            while (ans.peek().length() == i) {
                String t = ans.remove();
                for (char s : mapping[x].toCharArray())
                    ans.add(t + s);
            }
        }
        return ans;
    }

参考链接
1 链接1 
2 链接2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值