思考过程:
第一步要把‘2’-‘9’这样的字符转成对应的字符串,可以使用写一个方法,用switch返回,也可以使用hashmap(测试发现后者效率更好)。这时得到一个字符串数组,题意相当于使用这个字符串数组,每个字符串取一个字符,可以构成的所有字符。这时考虑两种解法,bfs和dfs。
代码实现:(bfs)
public List<String> letterCombinations(String digits) {
Map<Character, String> map = new HashMap<>();
map.put('2', "abc");
map.put('3', "def");
map.put('4', "ghi");
map.put('5', "jkl");
map.put('6', "mno");
map.put('7', "pqrs");
map.put('8', "tuv");
map.put('9', "wxyz");
List<String> ans = new ArrayList<>();
List<String> tem = new ArrayList<>();
for (char c : digits.toCharArray()) {
if (map.containsKey(c)) {
tem.add(map.get(c));
}
}
// bfs(ans, tem, 0);
List<Integer> ptag = new ArrayList<>();
for (int i = 0; i < tem.size(); i++) {
ptag.add(0);
}
dfs(ans, tem, ptag);
return ans;
}
public void bfs(List<String> ans, List<String> input, int index) {
if (index < input.size()) {
String s = input.get(index);
if (ans.size() == 0) {
for (char c : s.toCharArray()) {
ans.add(c + "");
}
} else {
List<String> tem = new ArrayList<>();
for (String an : ans) {
for (char c : s.toCharArray()) {
tem.add(an + c);
}
}
ans.clear();
ans.addAll(tem);
}
bfs(ans, input, index + 1);
}
}
dfs:
public void dfs(List<String> ans, List<String> input, List<Integer> ptag) {
if (input.size() == 0) {
return;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.size(); i++) {
String s = input.get(i);
if (s.length() > ptag.get(i)) {
sb.append(s.charAt(ptag.get(i)));
}
}
ans.add(sb.toString());
for (int i = ptag.size() - 1; i >= 0; i--) {
if (ptag.get(i) < input.get(i).length() - 1) {
ptag.set(i, ptag.get(i) + 1);
break;
} else {
ptag.set(i, 0);
if (i > 0) {
ptag.set(i - 1, ptag.get(i - 1) + 1);
if (ptag.get(i - 1) <= input.get(i - 1).length() - 1) {
break;
}
} else {
return;
}
}
}
dfs(ans, input, ptag);
}
bfs执行结果:
dfs执行结果:
可以看到两种解法效率差不多(dfs好一点,也有可能和代码实现有关)
算法复杂度分析:
两种解法的时间复杂度都是O(3^m * 4^n),其中m+n为输入字符串长度。
回溯法,和我的bfs思路差不多,但是代码跟简洁高效,代码如下:
//官方代码
public List<String> letterCombinations2(String digits) {
List<String> combinations = new ArrayList<String>();
if (digits.length() == 0) {
return combinations;
}
Map<Character, String> phoneMap = new HashMap<Character, String>() {{
put('2', "abc");
put('3', "def");
put('4', "ghi");
put('5', "jkl");
put('6', "mno");
put('7', "pqrs");
put('8', "tuv");
put('9', "wxyz");
}};
backtrack(combinations, phoneMap, digits, 0, new StringBuffer());
return combinations;
}
public void backtrack(List<String> combinations, Map<Character, String> phoneMap, String digits, int index, StringBuffer combination) {
if (index == digits.length()) {
combinations.add(combination.toString());
} else {
char digit = digits.charAt(index);
String letters = phoneMap.get(digit);
int lettersCount = letters.length();
for (int i = 0; i < lettersCount; i++) {
combination.append(letters.charAt(i));
backtrack(combinations, phoneMap, digits, index + 1, combination);
combination.deleteCharAt(index);
}
}
}
总结:
今天的解题过程还算满意,读完题后立即有了思路,并实现了bfs,而后花了点时间实现dfs,两种解法都通过。不过在代码实现上,和官方代码相比,还有很大的进步空间。