1. 程式人生 > 實用技巧 >Backtracking_17. 電話號碼的字母組合

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));
            }
        }
    }
}