17. 电话号码的字母组合
题目:
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
题解1:递归(DFS)
主要流程:
- 首先判断特例,当输入为空,则直接返回空串
- 定义字符数组,用于存储数字对应的字母
- 定义递归函数 findCombination(String digits, int index, String s),digits为数字数组,index为搜索到digits的下标索引,也可以理解为递归深度,s为当前递归节点的字母组合字符串
- 递归函数编写:
- 首先是递归终止条件,条件为index==digits.length,此时该节点为终止节点,将s添加到结果集并返回
- 之后取出当前数字对应的所有字母,for循环向下搜索所有的组合。
注意: 递归函数 findCombination(String digits, int index, String s)中,如果最后一个参数使用StringBuilder或StringBuffer,那么在for循环中,必须加入 s.deleteCharAt(index);,这是由于String是不可变的,而StringBuilder或StringBuffer都是可变对象,在后面的递归中,会对该对象有修改,所以需要回溯,删除加入的字符,消除影响。因为StringBuilder传入的都是同一个对象,所以在递归完成之后必须撤回上一次的操作,需要删除上一次添加的字符。而String每次改变之后传入的都是不同的对象。故无需撤销操作。
class Solution {
private List<String> res=new ArrayList<>();
String[] letterMaps={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
public List<String> letterCombinations(String digits) {
//特例判断
if (digits.length()==0||digits==null){
return res;
}
//调用递归函数
findCombination(digits,0,"");
return res;
}
public void findCombination(String digits,int index,String s){
//判断递归终止条件
if(index==digits.length()){
res.add(s);
return;
}
//取出当前节点字母表
char temp=digits.charAt(index);
String letter=letterMaps[temp-'0'];
//向下一层搜索
for (int i = 0; i < letter.length(); i++) {
findCombination(digits,index+1,s+letter.charAt(i));
}
}
}
题解2:队列求法
主要思路:
主要流程:
- 首先判断特例,当输入为空,则直接返回空串
- 定义字符数组,用于存储数字对应的字母
- 遍历输入的数字数组,执行如下操作:
- 取出当前数字对应的字母表,获取当前队列长度,遍历当前队列中的元素
- 取出队头元素,再遍历当前字母表,将队头元素与当前字母表中所有字母依次拼接,拼接完成后再次入队
- 最终的队列即为结果集
代码如下:
/**
* 解法二:使用队列
*/
class Solution {
private List<String> res = new ArrayList<>();
String[] letterMaps = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
public List<String> letterCombinations(String digits) {
//特例判断
if (digits.length() == 0 || digits == null) {
return res;
}
res.add("");
//遍历数字,对每个数字做如下操作
for (int i = 0; i < digits.length(); i++) {
char index=digits.charAt(i);
String letter=letterMaps[index-'0'];
//获取当前队列长度
int queueLength=res.size();
for (int j = 0; j < queueLength; j++) {
//取出队头元素
String temp=res.remove(0);
//接下来对元素与每个字母拼接后再加入队列中
for (int k = 0; k < letter.length(); k++) {
res.add(temp+letter.charAt(k));
}
}
}
return res;
}
}