其他分享
首页 > 其他分享> > leetcode刷题---热门百题---子集---dfs

leetcode刷题---热门百题---子集---dfs

作者:互联网

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:

输入:nums = [0]
输出:[[],[0]]

提示:

1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums 中的所有元素 互不相同

题解

这题看到输出结果就知道是要用dfs来做,不过dfs的终止条件和操作内容就久久想不出来,于是去翻看了题解找思路

dfs(cur,n) 参数表示当前位置是 \textit{cur}cur,原序列总长度为 nn。原序列的每个位置在答案序列中的状态有被选中和不被选中两种,我们用 tt 数组存放已经被选出的数字。在进入 \text{dfs}(\textit{cur}, n)dfs(cur,n) 之前 [0, \textit{cur} - 1][0,cur−1] 位置的状态是确定的,而 [\textit{cur}, n - 1][cur,n−1] 内位置的状态是不确定的,\text{dfs}(\textit{cur}, n)dfs(cur,n) 需要确定 \textit{cur}cur 位置的状态,然后求解子问题 {\text{dfs}(cur + 1}, n)dfs(cur+1,n)。对于 \textit{cur}cur 位置,我们需要考虑 a[\textit{cur}]a[cur] 取或者不取,如果取,我们需要把 a[\textit{cur}]a[cur] 放入一个临时的答案数组中(即上面代码中的 tt),再执行 {\text{dfs}(cur + 1}, n)dfs(cur+1,n),执行结束后需要对 tt 进行回溯;如果不取,则直接执行 {\text{dfs}(cur + 1}, n)dfs(cur+1,n)。在整个递归调用的过程中,\textit{cur}cur 是从小到大递增的,当 \textit{cur}cur 增加到 nn 的时候,记录答案并终止递归。可以看出二进制枚举的时间复杂度是 O(2 ^ n)O(2
n
)。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/subsets/solution/zi-ji-by-leetcode-solution/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

引用过来有些乱码,下面是根据题解的思路写的代码

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<Integer> val = new ArrayList<Integer>();
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        dfs(ans, val, 0, nums);
        return ans;
    }

    public void dfs(List<List<Integer>> ans, List <Integer> val, int cur, int[] nums){

        if (cur == nums.length) {
            ans.add(new ArrayList<Integer>(val));
            return;
        }

        val.add(nums[cur]);
        dfs(ans, val, cur + 1, nums);
        val.remove(val.size() - 1);
        dfs(ans, val, cur + 1, nums);
    }
}

下面摘录一个我之前也困惑的问题

ans.add(new ArrayList<Integer>(t));

为什么这里要new一个ArrayList来传入呢,而不能直接传入t呢?
这是因为如果不new的话,传入的是t的引用。如果不new 一下,每次添加进入ans的时t的引用,相当于一个指针,但是这个指针指向的栈内存里面的值(t)的值是随着程序变化的,直到t不变时,ans才确定自己的所有引用的堆内存里面真正的是什么,可是这些引用都相同,所以你最后看到的是空列表。
简单来说呢,如果不new直接传入t,后续对t的修改也会导致ans中的修改,直到最后t变为空的时候,ans也就变为空了。所以我们要深拷贝即new了一个t而不能浅拷贝

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/subsets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

标签:百题,cur,nums,dfs,---,ans,textit,new
来源: https://blog.csdn.net/weixin_46428711/article/details/115486085