回溯
我们可以从以下三个步骤考虑问题,首先是回溯的终止条件是什么,其次在当前我们可以选择什么,最后取消选择这个,因为需要回溯,换句话说某个值可以选择也可以不选择。
具体问题
全排列
public List<List<Integer>> permute(int[] arr) {
List<List<Integer>> permutes = new ArrayList<>();
List<Integer> permuteList = new ArrayList<>();
if (arr == null || arr.length ==0) {
return permutes;
}
// 用于判断某个值是否访问过
boolean[] hasVisited = new boolean[arr.length];
backtracking(arr,hasVisited,permuteList,permutes);
return permutes;
}
public void backtracking(int[] arr, boolean[] hasVisited, List<Integer> permuteList, List<List<Integer>> permutes) {
// 终止条件
if (arr.length == permuteList.size()) {
permutes.add(new ArrayList(permuteList));
return;
}
// 可以选择哪些值
for (int i = 0; i < arr.length; i++) {
// 这个值已经访问过
if (hasVisited[i]) {
continue;
}
hasVisited[i] = true;
// 选择该值
permuteList.add(arr[i]);
backtracking(arr,hasVisited,permuteList,permutes);
// 不选择该值
permuteList.remove(permuteList.size()-1);
hasVisited[i] = false;
}
}
@Test
public void test1(){
int[] arr = {1,2,3};
List<List<Integer>> permute = permute(arr);
System.out.println(permute);
}
分割字符串
分割字符串使得每个字串都是回文
class Solution {
public List<List<String>> partition(String s) {
List<List<String>> partitions = new ArrayList<>();
List<String> tempPartition = new ArrayList<>();
backtracking(s,tempPartition,partitions);
return partitions;
}
public void backtracking (String s, List<String> tempPartition,List<List<String>> partitions) {
// 终止条件
if (s.length() == 0) {
partitions.add(new ArrayList<>(tempPartition));
}
for (int i = 0; i < s.length(); i++) {
// 是否可以选择该值
if (isPalindrome(s.substring(0,i+1),0,i)){
// 选择
tempPartition.add(s.substring(0,i+1));
backtracking(s.substring(i+1),tempPartition,partitions);
// 不选择
tempPartition.remove(tempPartition.size() - 1);
}
}
}
public boolean isPalindrome(String s, int l,int r) {
while (l < r) {
if (s.charAt(l++) != s.charAt(r--)){
return false;
}
}
return true;
}
}