一、回溯法【路径,选择条件,结束条件】
回溯法,其实也是决策树,核心代码,就是for循环里面的递归,在递归调用之前【做出选择】,递归调用之后【撤销选择】
# 核心代码
result = []
def backtrack(路径,选择列表):
if 满足条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径,选择列表)
撤销选择
完整代码:
public class Permute {
List<List<Integer>> res = new ArrayList<List<Integer>>();
public List<List<Integer>> permute(int[] nums) {
if (nums == null || nums.length ==0) return res;
helper(nums,new ArrayList<Integer>());
return res;
}
private void helper(int[] nums, ArrayList<Integer> tmp) {
if (tmp.size() == nums.length){
res.add(new ArrayList<>(tmp));
return;
}
for (int i = 0; i < nums.length; i++) {
if (tmp.contains(nums[i])) continue;
tmp.add(nums[i]);
helper(nums,tmp);
tmp.remove(tmp.size()-1);
}
}
}
二、另辟蹊径新方法【搞怪的方法,很简单实用】
有时候,我觉得暴力一点也很好,但是我看到很多暴力的代码,需要比较交换很多次,严重的影响的代码的阅读,我想出了一个直接利用最大值循环,并利用Collections.shuffle的方法,因为最后的全排序的值时固定的,利用一个set集合,当达到了这个之后,直接退出循环就好。
你想到这个思想的小问题在哪里吗?
问题:只能计算输出没有重复元素的数组
public static void permute2(int[] nums) {
if (nums == null || nums.length == 0) {
//return new ArrayList<>();
}
// 共有多少种情况
int sum = 1;
for (int i = nums.length; i>0; i--) {
sum = sum * i;
}
System.out.println(sum);
ArrayList<Integer> list = new ArrayList<>();
for (int num : nums) {
list.add(num);
}
Set<List<Integer>> set = new HashSet<>();
for (int i = 0; i < 3000000; i++) {
Collections.shuffle(list);
ArrayList<Integer> templist = new ArrayList<>(list);
set.add(templist);
// set集合的大小 = 指定的数量 退出循环
if (set.size() == sum){
break;
}
System.out.println(i);
}
System.out.println(set);
}
执行结果:最终执行了10次就退出循环了 【每次执行总次数不一样】
评论