Backtracking_17. 电话号码的字母组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number
思路:
Backtracking(回溯)属于 DFS。有很多经典的问题,如八皇后。
- 普通 DFS 主要用在 可达性问题 ,这种问题只需要执行到特点的位置然后返回即可。
- 而 Backtracking 主要用于求解 排列组合 问题,例如有 { 'a','b','c' } 三个字符,求解所有由这三个字符排列得到的字符串,这种问题在执行到特定的位置返回之后还会继续执行求解过程。
因为 Backtracking 不是立即返回,而要继续求解,因此在程序实现时,需要注意对元素的标记问题:
- 在访问一个新元素进入新的递归调用时,需要将新元素标记为已经访问,这样才能在继续递归调用时不用重复访问该元素;
- 但是在递归返回时,需要将元素标记为未访问,因为只需要保证在一个递归链中不同时访问一个元素,可以访问已经访问过但是不在当前递归链中的元素。
class Solution { private static final String[] KEYS = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; public List<String> letterCombinations(String digits) { List<String> combinations = new ArrayList<>(); if (digits == null || digits.length() == 0) { return combinations; } doCombination(new StringBuilder(), combinations, digits); return combinations; } private void doCombination(StringBuilder prefix, List<String> combinations, final String digits) { if (prefix.length() == digits.length()) { combinations.add(prefix.toString()); return; } int curDigits = digits.charAt(prefix.length()) - '0'; String letters = KEYS[curDigits]; for (char c : letters.toCharArray()) { prefix.append(c); // 添加 doCombination(prefix, combinations, digits); prefix.deleteCharAt(prefix.length() - 1); // 删除 } } }
这段是官网的
class Solution { Map<String, String> phone = new HashMap<>() {{ put("2", "abc"); put("3", "def"); put("4", "ghi"); put("5", "jkl"); put("6", "mno"); put("7", "pqrs"); put("8", "tuv"); put("9", "wxyz"); }}; List<String> output = new ArrayList<>(); public List<String> letterCombinations(String digits) { if (digits.length() != 0) backtrack("", digits); return output; } public void backtrack(String combination, String next_digits) { if (next_digits.length() == 0) { //如果传进来的是空的,返回就是空的 output.add(combination); } else { //获取传进来的KEY,先获取digits的第一个内容,分割出来 String digit = next_digits.substring(0, 1); //获取对应的value String letters = phone.get(digit); for (int i = 0; i < letters.length(); i++) { //有value中有几个字母就循环几次,每次取出一个字母拼接起来 String letter = phone.get(digit).substring(i, i + 1); backtrack(combination + letter, next_digits.substring(1)); } } } }