题目
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number
解答
因为给出的号码字符串长度不定, 用常规的循环嵌套难以实现. 本题可以使用递归解决, 本文依旧使用循环法.(如输入数字为 “233”)
-
第一步先处理号码只有一位的情况的答案
[“a”,“b”,“c”] -
当进行第 i 步时, 会有前 i 步 已经找好的组合, 用这些已经找好的组合再与新的号码组
([“a”,“b”,“c”]与[“d”,“e”,“f”]组合结果为[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].) -
如果还有还有第三位以及更多位的数字, 反复执行第二步直到数字用完.
(此时找[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”] 与 [“d”,“e”,“f”] 的组合)
代码
/*
*给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
*给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
*
*示例:
*
*输入:"23"
*输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
*/
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
ostream& operator<<(ostream& os, vector<string>& v)
{
os << '[';
for (auto iter = v.begin(); iter < v.end() - 1; iter++)
{
os << '"' << *iter << "\" ," << endl;
}
os << '"' << *(v.end() - 1) << '"'<< ']';
return os;
}
class Solution {
public:
vector<string> letterCombinations(string digits) {
// 电话键盘的映射关系
map<char, string> tellphone = {
{ '2', "abc" },{ '3', "def" },
{ '4', "ghi" },{ '5', "jkl" },
{ '6', "mno" },{ '7', "pqrs"},
{ '8', "tuv" },{ '9', "wxyz"},
};
// 当输入数字只有一位的处理
vector<string> ans = {};
for (int i = 0; i < tellphone[digits[0]].size(); i++) {
string temp;
temp.push_back(tellphone[digits[0]][i]);
ans.push_back(temp);
}
// 当大于等于两位数字的处理
for (int i = 1; i < digits.size(); i++) {
vector<string> new_ans = {}; // 初始化新的 结果
// 把前n步找到所有组合 与 下一组号码组进行组合
for (int j = 0; j < tellphone[digits[i]].size(); j++) {
for (auto x : ans) {
new_ans.push_back(x + tellphone[digits[i]][j]);
}
}
ans = new_ans; // 新的组合赋值旧组合
}
return ans;
}
};
int main() {
string digits = { "233" };
Solution solv;
auto ans = solv.letterCombinations(digits);
sort(ans.begin(), ans.end());
cout << ans << endl;
return 0;
}
回溯法解答
代码
class Solution {
private String[] maps = new String[]{"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
private List<String> answer = new ArrayList<>();
public List<String> letterCombinations(String digits) {
if (digits.length() == 0) return answer;
recuir(digits, "");
return answer;
}
// 递归
// digits 代表还没有用到的电话数字, temp是已经尝试过来的字符串
public void recuir(String digits, String temp) {
if (digits.length() == 0) answer.add(temp);
else {
String newDigits = digits.substring(1);
// 找出单个数字所映射的字符串
int num = Integer.parseInt(digits.substring(0, 1));
String str = maps[num - 2];
// 回溯部分
for (int i = 0; i < str.length(); i++) {
String newTemp = temp + str.substring(i, i + 1);
recuir(newDigits, newTemp);
}
}
}
}