1. 程式人生 > >[LeetCode] 17. 電話號碼的字母組合

[LeetCode] 17. 電話號碼的字母組合

傳送門:[LeetCode] 17. 電話號碼的字母組合

題目描述

給定一個僅包含數字 2-9 的字串,返回所有它能表示的字母組合。

給出數字到字母的對映如下(與電話按鍵相同)。注意 1 不對應任何字母。

說明:

  • 儘管上面的答案是按字典序排列的,但是你可以任意選擇答案輸出的順序。

示例 :

輸入:"23"
輸出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].

分析

  • 一、迭代

    1. 判斷字串是否為空,為空直接返回,否則加入一個空字串

      List<String> res = new ArrayList<>();
      if (digits.isEmpty()) {
          return res;
      }
      res.add("");
    2. 建表,儲存每個數字代表的字串

      String[] table = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs",
                        "tuv", "wxyz" };
    3. 遍歷數字字串 digits 時建立一個臨時的字串陣列 temp ,通過數字取出字串,然後遍歷取出的字串中的所有字元,再遍歷當前 res 中的每一個字串,將字元加到字串後面,並加入到臨時字串陣列 temp 中,兩重遍歷完成後,更新 res 為 temp ;(看不懂文字直接看程式碼,程式碼容易看懂)

      for (char num : digits.toCharArray()) {
          List<String> temp = new ArrayList<>();
          for (char tail : table[num - '0'].toCharArray()) {
              for (String pre : res) {
                  temp.add(pre + tail);
              }
          }
          res = temp;
      }
  • 二、回溯

    1. 判空、建表與上述一致

    2. 遞迴函式寫法,使用 s 記錄當前的字串,level 記錄當前的字串字元個數;

      每次遞迴先判斷 level ,當 level 等於 digits 長度時,將字串s加入結果陣列 res ;

      否則通過 digits 中的數字取出字串,然後遍歷這個取出的字串,將每個字元都加到當前的組合後面,並呼叫遞迴函式。

      public void backtracking(String digits, String s, int level) {
          if (level == digits.length()) {
              res.add(s);
              return;
          }
          for (char tail : table[digits.charAt(level) - '0'].toCharArray()) {
              backtracking(digits, s + tail, level + 1);
          }
      }
    3. 呼叫遞迴函式時,傳入 s 為空字串"",level 為0;

      public List<String> letterCombinations(String digits) {
          if (digits.isEmpty()) {
              return res;
          }
          backtracking(digits, "", 0);
          return res;
      }
  • 三、佇列

    1. 判空、建表與上述一致

    2. 思想類似第一種迭代,但利用了佇列的先進先出,不用每次建立臨時的陣列

      for (int i = 0; i < digits.length(); i++) {
          // 把數字字元轉為數字
          int num = Character.getNumericValue(digits.charAt(i));
          // 利用了當前儲存的結果字串長度與當前遍歷的數字下標相等的條件進行判斷
          while (res.peek().length() == i) {
              String s = res.poll();
              for (char tail : table[num].toCharArray()) {
                  res.offer(s + tail);
              }
          }
      }

程式碼

  • 解法一:迭代

    class Solution {
        public List<String> letterCombinations(String digits) {
            List<String> res = new ArrayList<>();
            if (digits.isEmpty()) {
                return res;
            }
            res.add("");
            String[] table = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs",
                              "tuv", "wxyz" };
            for (char num : digits.toCharArray()) {
                List<String> temp = new ArrayList<>();
                for (char tail : table[num - '0'].toCharArray()) {
                    for (String pre : res) {
                        temp.add(pre + tail);
                    }
                }
                res = temp;
            }
            return res;
        }
    }
  • 解法二:回溯

    class Solution {
        List<String> res = new ArrayList<>();
        String[] table = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv",
                          "wxyz" };
    
        public List<String> letterCombinations(String digits) {
            if (digits.isEmpty()) {
                return res;
            }
            backtracking(digits, "", 0);
            return res;
        }
    
        public void backtracking(String digits, String s, int level) {
            if (level == digits.length()) {
                res.add(s);
                return;
            }
            for (char tail : table[digits.charAt(level) - '0'].toCharArray()) {
                backtracking(digits, s + tail, level + 1);
            }
        }
    }
  • 解法三:佇列

    public List<String> letterCombinations(String digits) {
        LinkedList<String> res = new LinkedList<>();
        String[] table = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs",
                          "tuv", "wxyz" };
        if (digits.isEmpty()) {
            return res;
        }
        res.add("");
        for (int i = 0; i < digits.length(); i++) {
            // 把數字字元轉為數字
            int num = Character.getNumericValue(digits.charAt(i));
            // 利用了當前儲存的結果字串長度與當前遍歷的數字下標相等的條件進行判斷
            while (res.peek().length() == i) {
                String s = res.poll();
                for (char tail : table[num].toCharArray()) {
                    res.offer(s + tail);
                }
            }
        }
        return res;
    }

小結

Character.getNumericValue(char ch)

該方法獲取引數ch的數值,有三種返回值

  1. 若ch字元的數值為非負整數,返回ch字元對應的數值
  2. 若為不是非負整數,返回-2
  3. 若字元沒有數值,返回-1