力扣labuladong一刷day68天回溯大集合

力扣labuladong一刷day68天回溯大集合

文章目录

      • 力扣labuladong一刷day68天回溯大集合
      • 一、491. 非递减子序列
      • 二、46. 全排列
      • 三、47.全排列 II

一、491. 非递减子序列

题目链接:https://leetcode.cn/problems/non-decreasing-subsequences/description/
求非递减子序列,是有重复元素的,不能排序,自然没法用之前的横向去重的策略(if( i > index && nums[i] == nums[i-1])continue;)。这个去重策略只能是排序后,让重复元素都挨着才能用。那么树层该如何去重?就需要使用一个set数组,每次递归都是一个新的数组,不影响纵向,但横向for循环时会记录靠左的孩子使用的元素,遇到重复元素就跳过去,避免重复使用。

class Solution {
   List<List<Integer>> arrayLists;
    List<Integer> list;
    public List<List<Integer>> findSubsequences(int[] nums) {
        arrayLists = new ArrayList<>();
        list = new ArrayList<>();
        backTracking(nums, 0);
        return arrayLists;
    }

    void backTracking(int[] nums, int index) {
        if (list.size() > 1) {
            arrayLists.add(new ArrayList<>(list));
        }
        Set<Integer> set = new HashSet<>();
        for (int i = index; i < nums.length; i++) {
            if (list.size()>0 && list.get(list.size()-1) > nums[i]) continue;
            if (set.contains(nums[i])) continue;
            set.add(nums[i]);
            list.add(nums[i]);
            backTracking(nums, i+1);
            list.remove(list.size()-1);
        }
    }
}

二、46. 全排列

题目链接:https://leetcode.cn/problems/permutations/description/
思路:排列问题,和组合问题还不一样,排列问题不需要indexStart,也就是for循环是固定的0到结束,但是纵向需要去重,避免使用重复元素,这时可以使用used数组,标记为true即跳过,只有向下递归才会遇到重复元素跳过,横向是没有重复元素的。

class Solution {
    
   List<List<Integer>> arrayLists;
    List<Integer> list;
    boolean[] visited;
    public List<List<Integer>> permute(int[] nums) {
        arrayLists = new ArrayList<>();
        list = new ArrayList<>();
        visited = new boolean[nums.length];
        backTracking(nums);
        return arrayLists;
    }
    void backTracking(int[] nums) {
        if (list.size() == nums.length) {
            arrayLists.add(new ArrayList<>(list));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (visited[i]) continue;
            visited[i] = true;
            list.add(nums[i]);
            backTracking(nums);
            visited[i] = false;
            list.remove(list.size()-1);
        }
    }


}

三、47.全排列 II

题目链接:https://leetcode.cn/problems/permutations-ii/description/
思路:nums = [1,1,2]本题包含重复元素,又是排序,所以,不光要纵向去重,也需要横向去重,纵向去重使用used数组,横向去重需要排序,而且used[i-1]为false,即可起到去重的效果。

class Solution {
  List<List<Integer>> arrayLists;
    List<Integer> list;
    boolean[] used;
    public List<List<Integer>> permuteUnique(int[] nums) {
        arrayLists = new ArrayList<>();
        list = new ArrayList<>();
        used = new boolean[nums.length];
        Arrays.sort(nums);
        backTracking(nums);
        return arrayLists;
    }
    void backTracking(int[] nums) {
        if (list.size() == nums.length) {
            arrayLists.add(new ArrayList<>(list));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i]) continue;
            if (i > 0 && nums[i] == nums[i-1] && !used[i-1]) continue;
            used[i] = true;
            list.add(nums[i]);
            backTracking(nums);
            used[i] = false;
            list.remove(list.size()-1);
        }
    }
}

你可能感兴趣的:(力扣算法题,leetcode,数据结构,算法)