题目类型:
字符串
题意:
类似电话键盘,给出一个由数字组成的字符串,输出对应字母的所有组合。
例子:
Input:Digit string “23”
Output: [“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
我的思路:递归
22%
- 前两个任意组合,结果再与第三个组合,结果再与第四个组合…以此类推。
- 键盘数字对应的字母可以存到数组,也可以存到hashMap
步骤:
- 将数字对应的字母列表存到hashMap
- 递归函数的参数:list1, list2,当前已经计算到的digit下标cur,digit长度, map)
- 将digit[0]和digit[1]对应的列表采用双层循环计算出组合存入新的列表list,若++cur不超出digit下标,那么传入list和map.get(digit[++cur]),递归计算。
class Solution {
public List<String> letterCombinations(String digits) {
if (digits == null || digits.equals("")) {
return new ArrayList<>();
}
Map<Integer, List<String>> map = new HashMap<>();
map.put(2, Arrays.asList("a", "b", "c"));
map.put(3, Arrays.asList("d", "e", "f"));
map.put(4, Arrays.asList("g", "h", "i"));
map.put(5, Arrays.asList("j", "k", "l"));
map.put(6, Arrays.asList("m", "n", "o"));
map.put(7, Arrays.asList("p", "q", "r", "s"));
map.put(8, Arrays.asList("t", "u", "v"));
map.put(9, Arrays.asList("w", "x", "y", "z"));
char[] digit = digits.toCharArray();
int len = digit.length;
if (len == 1) {
return map.get(digit[0] - '0');
}
return calComponent(map.get(digit[0] - '0'), map.get(digit[1] - '0'), 1, len, map, digit);
}
private List<String> calComponent(List<String> list1, List<String> list2, int cur, int len, Map<Integer, List<String>> map, char[] digit) {
List<String> list = new ArrayList<>();
for (String s1 : list1) {
for (String s2 : list2) {
list.add(s1 + s2);
}
}
if (++cur < len) {
return calComponent(list, map.get(digit[cur] - '0'), cur, len, map, digit);
}
return list;
}
}
方法二:改进递归
递归参数:给出的数字组合digits,结果列表res,当前的字母组合cur,当前遍历的digits位置i
1. 如果i为digits.length(),证明digits便利完毕,那么将当前组合cur加入res,return
2. 否则,需要将本层的字母叠加上:
- 得到本层数字对应的字母表
- 对于每一个字母,与之前的cur组合加上后传入新的递归
public List<String> letterCombinations(String digits) {
List<String> res = new ArrayList<>();
if (digits == null || digits.equals("")) return res;
String[] letters = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
calComponent(digits, res, "", 0, letters);
return res;
}
private void calComponent(String digits, List<String> res, String cur, int i, String[] letters) {
// TODO Auto-generated method stub
if (i == digits.length()) {
res.add(cur);
return;
}
String str = letters[digits.charAt(i) - '0'];
for (char c : str.toCharArray()) {
calComponent(digits, res, cur + c, i + 1, letters);
}
}
递归时注意,要传递cur+c,因为如此传递,才会在下一层得到cur+c,且返回到本层时 cur依然维持原有的cur。若改变cur=cur+c,那么cur全改变。
方法三:队列
- (类似于BFS)假设当前遍历到digits第i个字符,将队列中长度为i-1的出队,循环加上当前字符对应的字母后入队列。
- 因为结果要求输出List,所以定义队列不能用传统的Queue res = new LinkedList<>(); 而需要用==LinkedList res = 。。。来定义。==
class Solution {
//方法三:队列
public List<String> letterCombinations(String digits) {
LinkedList<String> res = new LinkedList<>();
if (digits.length() == 0) {
return res;
}
String[] letters = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
res.add("");
for (int i = 0; i < digits.length(); i++) {
int cur = digits.charAt(i) - '0';
while (res.peek().length() == i) {//因为i下标是当前位置-1
String temp = res.remove();
for (char c : letters[cur].toCharArray()) {
res.offer(temp + c);
}
}
}
return res;
}
}