2022-09-08 【我的刷题日记】90 子集 491递增子序列

思路:本题相比78子集,可能会出现重复的集合元素,且最后要求的子集不能出现重复,所以需要对子集进行去重操作,因为回溯问题常常可以抽象成一颗N叉树,本题的去重则要求二叉树的树枝间可以出现重复的元素,但是同一层不能出现相同的元素,所以我们可以使用used数组来进行去重,used数组为false的时候表示为同一树层元素,used数组为true的时候表示为同一树枝的元素。当然去重同一树层的重复元素还有另一种不用使用used数组的方法 用i>start 进行判断.

这里关于used数组的表示可参照卡尔大佬的图

used数组判断重复的示例.png

注意这里计算used数组的时候要看当前的父节点,而不是兄弟节点

class Solution {
//在78子集的基础上怎加去重的操作
    List> res = new ArrayList<>();
    List list = new LinkedList<>();
//    去重也可以使用used数组
    boolean[] used;
    public List> subsetsWithDup(int[] nums) {
        used = new boolean[nums.length];
        Arrays.sort(nums);
        backTracking(nums,0);
        return res;
    }
    public void backTracking(int[] nums,int start){
        res.add(new ArrayList<>(list));
        if (start >= nums.length){
            return;
        }
        for (int i = start; i < nums.length;i++){
            // 跳过当前树层使用过的、相同的元素
            if(i > start && nums[i] == nums[i - 1]) continue;
//            使用used数组排除同一树层使用过的相同元素
//            if(i > 0 && nums[i] == nums[i - 1]&& used[i] == false) continue;
            list.add(nums[i]);
//            used[i]  = true;
            backTracking(nums,i + 1);
//            used[i] = false;
            list.remove(list.size() -1 );
        }
    }
}

思路:本题是一道易错题,看起来和子集很像,只需要在子集的基础上,增加添加到结果集的时候判断长度的逻辑即可,但是本题是不能先进行排序再进行回溯的,因为排序之后就变成了递增数组,和题意不符合,出现以下的错误

错误示例.png

所以本题应该单独的增加判断递增的逻辑和进行去重的方法,不能使用之前排序去重的那一套代码。判断递增:判断当前nums[i]是否大于list的最后一个元素即可。
去重:使用map进行去重,key-value对于nums[i]和出现的次数

class Solution {
    List> res = new ArrayList<>();
    LinkedList list = new LinkedList<>();

    public List> findSubsequences(int[] nums) {
        backTracking(nums,0);
        return res;
    }
    public void backTracking(int[] nums,int start){
        if (list.size() > 1){
            res.add(new ArrayList<>(list));
        }
//        map每次递归都会被刷新 不会影响到下一层的情况
        Map map = new HashMap<>();
        for (int i = start; i < nums.length;i++){
//            保证是递增的
            if(!list.isEmpty() && nums[i] < list.getLast()) continue;
//            用hashmap去重,同一个数字在一层只能出现一次
            if (map.getOrDefault(nums[i],0) >= 1) continue;
            map.put(nums[i],map.getOrDefault(nums[i],0) + 1 );

            list.add(nums[i]);

            backTracking(nums,i + 1);

            list.remove(list.size() -1 );

        }
    }
}

你可能感兴趣的:(2022-09-08 【我的刷题日记】90 子集 491递增子序列)