不做舔狗,好好学习,冲!
leetcode 46. 全排列
思路:
- 很明显的使用回溯算法,该题简单就简单在不包含重复元素
public List<List<Integer>> permute(int[] nums) {
List<Integer> stack = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
backtrack(nums, stack, result);
return result;
}
public void backtrack(int[] nums, List<Integer> stack, List<List<Integer>> result){
if (stack.size() == nums.length){
result.add(new ArrayList<>(stack));
}
for (int i =0;i<nums.length;i++){
int num = nums[i];
if (stack.contains(num))continue;
stack.add(num);
backtrack(nums, stack, result);
stack.remove(stack.size() -1);
}
}
leetcode 47. 全排列 II
思路
- 这个比上一个题就难得多了,他包含重复元素,最终解里还不能有重复元素,要考虑去重,当然可以用set,但是估计run不过全部,需要想办法剪枝
- 去重思考:(后续也能用到)
- 排序,保证重复的数排在一起
- 在回溯算法中,如果stack中不包含前一个元素,说明前一个元素要么进入最终结果了,要么不满足要求,如果此时nums[i-1] = nums[i],选择这个i加入stack一定是重复的
public static List<List<Integer>> permuteUnique2(int[] nums) {
List<Integer> stack = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
backtrack47(nums, stack, result, 0);
return result;
}
private static void backtrack47(int[] nums, List<Integer> stack, List<List<Integer>> result, int index) {
if (stack.size() == nums.length){
List<Integer> list = new ArrayList<>();
for (int i : stack){list.add(nums[i]);}
result.add(list);
return;
}
for (int i =0;i<nums.length;i++){
int num = nums[i];
if (stack.contains(i))continue;
if (i > 0 && nums[i-1] == num && !stack.contains(i-1)){continue;}
stack.add(i);
backtrack47(nums, stack, result,i+1);
stack.remove(stack.size() -1);
}
}
- 另一种思路,用一个数组vis保存该位置是否被使用过,如果nums[i-1] == nums[i],切vis[i-1]使用过了,那么此时stack加入i,一定也是重复的解
//47. 全排列 II
public static List<List<Integer>> permuteUnique(int[] nums) {
List<Integer> stack = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
boolean[] vis = new boolean[nums.length];
backtrack47(nums, stack, result, 0, vis);
return result;
}
private static void backtrack47(int[] nums, List<Integer> stack, List<List<Integer>> result, int index, boolean[] vis) {
if (stack.size() == nums.length){
List<Integer> list = new ArrayList<>();
for (int i : stack){list.add(nums[i]);}
result.add(list);
return;
}
for (int i =0;i<nums.length;i++){
int num = nums[i];
if (stack.contains(i))continue;
if (vis[i] || (i>0 && nums[i-1]==nums[i] && vis[i-1])) continue;
stack.add(i);
vis[i] = true;
backtrack47(nums, stack, result,i+1,vis);
stack.remove(stack.size() -1);
vis[i]=false;
}
}
这两种思路都能run,都可以借鉴
leetcode 77. 组合
思路:
- 和46没啥区别,很简单的题目
public List<List<Integer>> combine(int n, int k) {
List<Integer> stack = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
int[] arr = new int[n];
for (int i =0;i<n;i++) {arr[i] = i+1;}
backtrack77(arr, stack, result, k, 0);
return result;
}
private void backtrack77(int[] arr, List<Integer> stack, List<List<Integer>> result, int k, int index) {
if (stack.size() == k) {
result.add(new ArrayList<>(stack));
return;
}
for (int i =index;i<arr.length;i++){
int num = arr[i];
if (stack.contains(num)) { continue; }
stack.add(num);
backtrack77(arr, stack,result, k,i+1);
stack.remove(stack.size() -1);
}
}
leetcode 78. 子集
思路
- 这道题也很简单,能run100%也是没想到
- 关键就是这种情况下,解加入到result中后,不要ruturn,继续回溯
public List<List<Integer>> subsets(int[] nums) {
List<Integer> stack = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
backtrack78(nums, stack, result, 0);
return result;
}
private void backtrack78(int[] nums, List<Integer> stack, List<List<Integer>> result, int index) {
if (stack.size() <= nums.length){
result.add(new ArrayList<>(stack));
}
for (int i = index;i< nums.length;i++){
int num = nums[i];
if (stack.contains(num)) continue;
stack.add(num);
backtrack78(nums, stack, result, i+1);
stack.remove(stack.size() -1);
}
}
leetcode 90. 子集 II
思路:
- 这道题借鉴了78题和47题的去重思路:
- 去重思考:(和47题一样的思路)
- 排序,保证重复的数排在一起
- 在回溯算法中,如果stack中不包含前一个元素,说明前一个元素要么进入最终结果了,要么不满足要求,如果此时nums[i-1] = nums[i],选择这个i加入stack一定是重复的
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<Integer> stack = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(nums);
backtrack90(nums, stack, result, 0);
return result;
}
private void backtrack90(int[] nums, List<Integer> stack, List<List<Integer>> result, int index) {
if (stack.size() <= nums.length){
List<Integer> list = new ArrayList<>();
for (int i : stack){list.add(nums[i]);}
result.add(list);
}
for (int i = index;i< nums.length;i++){
int num = nums[i];
if (stack.contains(i)) continue;
if (i > 0 && !stack.contains(i-1) && nums[i-1] == num) continue;
stack.add(i);
backtrack90(nums, stack, result, i+1);
stack.remove(stack.size() -1);
}
}
做题上瘾,本来想复习juc包的,看看晚上有没有时间复习吧!