1、回溯法
思想:回溯法,尝试当前执行、若不合适、则回退到上一步
例:
a b c
确定第一个元素: 确定第二个元素: 剩下最后一个:
a (b c) a b
a c
b (a c) b a
b c
c (a b) c a
c b
1、每次先确定第一个元素
2、然后再确定子序列的第一个元素..
3、每次交换完成后、需退回到原来状态
4、结束条件为start==end
public static void full(char[] array,int start,int end){
if(start==end){
System.out.println(Arrays.toString(array));
}else{
for(int i=start;i<=end;i++){
swap(array,i,start);
full(array,start+1,end);
swap(array,i,start);
}
}
}
private static void swap(char[] array,int i,int j){
char temp=array[i];
array[i]=array[j];
array[j]=temp;
}
2、递归法
数组全排列
- 法1
public static void permuteUnique(int[] nums) {
Arrays.sort(nums);
boolean[] used = new boolean[nums.length];
dfs(nums, used, new ArrayList<Integer>());
}
private static void dfs(int[] nums, boolean[] used, List tmp) {
if (tmp.size() == nums.length) {
System.out.println(tmp);
} else {
for (int i = 0; i < nums.length; ++i) {
// 已经添加过的元素,直接跳过
if (used[i]) {
continue;
}
// 上一个元素和当前相同,并且没有访问过就跳过
if ((i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) {
continue;
}
tmp.add(nums[i]);
used[i] = true;
dfs(nums, used, tmp);
used[i] = false;
tmp.remove(tmp.size() - 1);
}
}
}
- 法2
public static List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> tmp = new ArrayList<>();
backtrack(nums,tmp, res);
return res;
}
private static void backtrack(int[] nums, List<Integer> tmp, List<List<Integer>> res) {
if (tmp.size() == nums.length){
res.add(new ArrayList<>(tmp));
}else {
// 每次遍历所有元素
for (int j = 0; j < nums.length; j++) {
// 不能包含重复
if (tmp.contains(nums[j])){
continue;
}
tmp.add(nums[j]);
// 全排列位置不前移
backtrack(nums, tmp, res);
tmp.remove(tmp.size()-1);
}
}
}
- 法3
public static List<List<Integer>> permute(int[] nums) {
List<List<Integer>> lists = new ArrayList<>();
boolean[] used = new boolean[nums.length];
backtrack(nums,used, lists, new LinkedList<>());
return lists;
}
public static void backtrack(int[] nums,boolean[] used, List<List<Integer>> list, LinkedList<Integer> array){
if (array.size() == nums.length){
list.add(new ArrayList<>(array));
return;
}
for (int i = 0 ; i < nums.length; i++){
if (used[i]){
continue;
}
array.add(nums[i]);
used[i] = true ;
backtrack(nums,used, list, array);
//删除后一个节点,向上回溯
used[i] = false ;
array.removeLast();
}
}