題目
給定一個僅包含數字 2-9 的字符串,返回所有它能表示的字母組合。
給出數字到字母的映射如下(與電話按鍵相同)。注意 1 不對應任何字母。
示例:
輸入:"23"
輸出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
說明:
盡管上面的答案是按字典序排列的,但是你可以任意選擇答案輸出的順序。
(題目鏈接 https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/)
問題分析
剛拿到這道題的時候沒什么思路,只能順着邏輯想。每個數字對應着三個或者四個字母,也就是說每個位置我們會有三個或者四個選擇。那么似乎我們可以用遞歸來解決問題,因為每個位置的字母我們都需要做多種選擇,而做出這種選擇后下一個位置同樣也需要這么做。那么我們先依據這個思路寫一個遞歸函數
/*
C++代碼
*/
/*
ret 為儲存最終結果的數組
map 是字母到數字的映射表
digits 是一串要轉換數字
s 由數字轉換成的字符串
*/
void fun(vector<string>& ret, const char map[8][5], const string& digits, string& s) {
if (s.length() < digits.length()) {
for (int i = 0; i < strlen(map[(digits[s.length()] - '0') - 2]); i++) {
s.push_back(map[(digits[s.length()] - '0') - 2][i]);
fun(ret,map,digits,s);
s.pop_back();
}
}
else if (s.length() == digits.length()) {
ret.push_back(s);
}
}
可能有朋友發現這就是一個深度優先搜索的過程,那么恭喜,后面的內容將十分容易理解,如果沒有反應過來,后面還有圖片助於理解。
這個函數的部分執行過程見下圖(其實是畫圖太麻煩懶得畫全過程,也沒必要),看了之后理解起來應該更容易。
由於最終我們要返回一個數組給LeetCode,外層套上一個函數
/*
C++代碼
*/
vector<string> letterCombinations(string digits) {
vector<string> ret;
if (digits.length() == 0) {
return ret;
}
char map[8][5] = {
{'a','b','c',0},
{'d','e','f',0},
{'g','h','i',0},
{'j','k','l',0},
{'m','n','o',0},
{'p','q','r','s',0},
{'t','u','v',0},
{'w','x','y','z',0}
};
string s;
fun(ret, map, digits, s);
return ret;
}
時間復雜度O(4^n) ,空間復雜度O(n)。