78.子集、90.子集II

62 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

78.子集

题目分析

题目给出一个整数,数组不包含重复元素,要求返回该数组所有可能的子集。要求解集不能包含重复的子集。

这道题是典型的子集问题,是回溯算法解决的问题中的一个。下面我们就使用回溯的方法来解决它。

解题

依旧是回溯三部曲:

  1. 递归函数的参数

回溯函数的参数为循环的开始位置,因为我们要通过横向循环,遍历整个数组,所以需要一个开始位置来确定从哪里开始遍历。

  1. 回溯函数终止条件

当开始位置大于数组的长度时结束,不过这个条件可有可无,因为for循环的遍历条件就是开始位置小于数组长度。

  1. 单层搜索的过程

因为我们需要所有的子集,所以不像组合问题一样,只需要叶子节点。这个问题我们需要树的所有节点。所以我们需要进行回溯,并将所有的节点存到结果数组中。

function backstracing(startIndex) {
        res.push([...path])      
        for(let i = startIndex;i < nums.length;i++) {
            path.push(nums[i])
            backstracing(i + 1)
            path.pop()
        }
    }

90.子集II

题目分析

这道题与上一道题的区别就是给出的整数数组其中可能包含重复的元素。这样我们如果想要得到不包含重复的子集,就需要进行去重操作。

解题

由于需要去重操作,所以我们首先将给出的数组按顺序排列。接下来我们需要知道重复的情况,也就是什么情况下结果会重复。

递归遍历时,也就是竖向遍历时,是不会出现重复的情况的。重复的情况出现在树的同一层上,所以我们需要判断for循环时是否当前遍历的元素和上一个便利的元素相同。如果相同,我们就把这一个遍历结束。

只需要加上下面的判断即可:

if(i > startIndex && nums[i] === nums[i - 1]) {
     continue
}