17_電話號碼的字母組合
【問題描述】
給定一個僅包含數字 2-9
的字串,返回所有它能表示的字母組合。答案可以按任意順序返回。給出數字到字母的對映如下(與電話按鍵相同)。注意1不對應任何字母。
示例一:
輸入:digits = "23"
輸出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例二:
輸入:digits = ""
輸出:[]
示例三:
輸入:digits = "2"
輸出:["a","b","c"]
提示:
0 <= digits.length <= 4
digits[i]
是範圍['2', '9']
的一個數字。
【演算法設計思想】
本題主要是用到了DFS,即深度優先搜尋的思想。在此我們需要搞清楚DFS的基本思想和虛擬碼是怎麼樣的。
DFS的演算法設計思想:一種用於遍歷或搜尋樹或圖的演算法。DFS的基本思想是從根節點開始(選擇某個搜尋起始節點),先儘可能深的搜尋樹的分支,如果到底了(即到達一個葉子節點或者當前節點沒有任何未訪問的子節點),就回溯到上一層,繼續儘可能深的搜尋其它未搜尋過的子節點,這個過程一直持續到所有的節點都被訪問過為止。
虛擬碼如下:
procedure DFS(G,V):
make V as visited;
for each w in G.adjacent(v) do //遍歷v的所有鄰接頂點
ifw is not visited then
DFS(G,w)//遞迴訪問w
我們可以把這個問題看成是一個搜尋的問題,在這裡,2對應abc,3對應def,我們只需要求其組合就可以了,本質上是一個樹形的結構,我們對這個樹進行DFS即可得到答案,所以透過本題我們要複習DFS這個知識點。
【演算法描述】
C++:
class Solution
{
public:
// 儲存結果的容器
std::vector<std::string> ans;
// 字串對映陣列,對應數字鍵上的字母
std::string strs[10] = {",", "", "abc", "def", "ghi", "jkl",
"mno", "pqrs", "tuv", "wxyz"};
// 主要的方法,用於獲取電話號碼的字母組合
std::vector<std::string> letterCombinations(std::string digits)
{
// 如果輸入的數字字串為空,則直接返回空的結果集
if (digits.empty())
{
return ans;
}
// 從第一個數字開始深度優先搜尋
dfs(digits, 0, "");
// 返回所有可能的組合
return ans;
}
// 深度優先搜尋 (DFS) 輔助方法
void dfs(const std::string &digits, int idx, std::string combine)
{
// 當前索引等於輸入字串的長度時,說明已經處理完了一個完整的組合
if (idx == digits.length())
{
// 將當前組合加入結果集中
ans.push_back(combine);
return;
}
// 獲取當前數字對應的字母字串
const std::string &s = strs[digits[idx] - '0'];
// 遍歷當前數字對應的字母字串
for (size_t i = 0; i < s.length(); i++)
{
// 將當前字母新增到組合字串中
combine.push_back(s[i]);
// 遞迴地進行下一步搜尋
dfs(digits, idx + 1, combine);
// 回溯:移除最後一個字元,以便嘗試下一個字母
combine.pop_back();
}
}
};
Java:
import java.util.ArrayList;
import java.util.List;
class Solution {
// 儲存結果的容器
private List<String> ans = new ArrayList<>();
// 字串對映陣列,對應數字鍵上的字母
private String[] strs = {",", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
// 主要的方法,用於獲取電話號碼的字母組合
public List<String> letterCombinations(String digits) {
// 如果輸入的數字字串為空,則直接返回空的結果集
if (digits.isEmpty()) {
return ans;
}
// 從第一個數字開始深度優先搜尋
dfs(digits, 0, "");
// 返回所有可能的組合
return ans;
}
// 深度優先搜尋 (DFS) 輔助方法
private void dfs(String digits, int idx, String combination) {
// 當前索引等於輸入字串的長度時,說明已經處理完了一個完整的組合
if (idx == digits.length()) {
// 將當前組合加入結果集中
ans.add(combination); // 修改為 add 而不是 append
return;
}
// 獲取當前數字對應的字母字串
String s = strs[digits.charAt(idx) - '0']; // 使用 charAt 獲得字元而不是使用索引
// 遍歷當前數字對應的字母字串
for (int i = 0; i < s.length(); i++) {
// 將當前字母新增到組合字串中
combination += s.charAt(i); // 使用 += 新增字元
// 遞迴地進行下一步搜尋
dfs(digits, idx + 1, combination);
// 回溯:移除最後一個字元,以便嘗試下一個字母
combination = combination.substring(0, combination.length() - 1); // 使用 substring 方法回溯
}
}
}
Python:
from typing import List
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
# 結果容器
ans: List[str] = []
# 字串對映字典,對應數字鍵上的字母
strs = {
",": "",
"": "",
"2": "abc",
"3": "def",
"4": "ghi",
"5": "jkl",
"6": "mno",
"7": "pqrs",
"8": "tuv",
"9": "wxyz"
}
# 如果輸入的數字字串為空,則直接返回空的結果集
if not digits:
return ans
# 深度優先搜尋 (DFS) 輔助方法
def dfs(digits: str, idx: int, combination: str):
# 當前索引等於輸入字串的長度時,說明已經處理完了一個完整的組合
if idx == len(digits):
ans.append(combination)
return
# 獲取當前數字對應的字母字串
s = strs[digits[idx]]
# 遍歷當前數字對應的字母字串
for i in range(len(s)):
# 將當前字母新增到組合字串中
combination += s[i]
# 遞迴地進行下一步搜尋
dfs(digits, idx + 1, combination)
# 回溯:移除最後一個字元,以便嘗試下一個字母
combination = combination[:-1]
# 從第一個數字開始深度優先搜尋
dfs(digits, 0, "")
# 返回所有可能的組合
return ans