以下都是个人理解,不一定准确
像这种电话号码的全排列问题,一般就可以用回溯+剪枝的算法
回溯算法有个模板可以参考下,基本就是如下的流程:
回溯模板
LinkedList list = new LinkedList<>();
public void backtrack(排序组合,条件,depth) {
if(条件成立) {
list.add(排序)
return;
}
for (排序: 排序组合) {
if(条件不符合) {
//剪枝
break;
}
backtrack(排序组合,条件,depth+1);
list.remove(list.length-1);
}
17题 leetcode 代码如下:
private static List<String> letterCombinations(String digits) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "");
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> result = new ArrayList<>();
if (digits == null || digits.length() == 0) {
return result;
}
backTrack(map, result, 0, digits, new StringBuilder().append(""));
return result;
}
private static void backTrack(Map<Integer, String> map, List<String> result, int depth, String digits, StringBuilder sb) {
if (depth == digits.length()) {
result.add(sb.toString());
return;
}
String value = map.get((int) digits.toCharArray()[depth] - 48);
if (value != "") {
for (char digit : value.toCharArray()) {
sb.append(digit);
backTrack(map, result, depth + 1, digits, sb);
sb.deleteCharAt(sb.length() - 1);
}
}
}
backTrack 里面需要放置哪些入参、在什么条件下满足并结束递归 难点在这里
解释下如上的代码逻辑:
比如输入了"23",
我先从map中获取2对应的字符串,是abc,然后对这个字符串进行for循环遍历,先将stringBuilder加入a进去,
然后递归,将当前深度+1,这个时候会获取到3对应的字符串,是def,重复上面for循环遍历,将d加入到stringBuilder中,
得到子串ad,然后递归,深度+1后等于2,这个时候递归结束,得到字符ad。
本次递归结束后,得到字符串ad,并回溯将最后一个字符删除,得到a。
然后接着继续遍历def,得到子串ae,然后得到af。
这个时候a的所有遍历就结束了。
然后依次遍历b,依次遍历c。