LeetCode热题HOT100之第二十二题:子集

题目:给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

//解题方法1:迭代思想:首先我们把数组中的每一位是否可以用到通过二进制表示,用到为1,用不到为0,然后求出数组长度n,则可以得到一共有2^n个子集,空集其实就是0000……表示,然后因为不知道每次输入的数组的长度,所以可以用链表来表示
// class Solution {
//      //用于存放每一个子集
//         List<Integer> t = new ArrayList<Integer>();
//         //把每一个子集放如到链表中
//         List<List<Integer>> ans = new ArrayList<List<Integer>>();

    public List<List<Integer>> subsets(int[] nums) {
        //求数组长度
        int n = nums.length;
        //要求出2^n个子集,因此我们要循环2^n次,i的值其实就是对应着数组中的每一位,然后我们根据i进行“位”的操作,来输出每一位
       for(int i=0 ; i<(1<<n) ; i++){
           //每次循环我们都要把t清空
           t.clear();
           //然后我们再根据i进行“位比较”,因为我们把i换算成二进制数,然后把每一位是1的都对应着添加到t中
           for(int j=0 ; j<n  ; j++){
               //1<<j是为了和二进制的每一位进行与逻辑,比如1<0=1就是……00001,1<1=2就是……00010
               if((i&(1<<j))!=0){
                   t.add(nums[j]);
               }
           }
           ans.add(new ArrayList<Integer>(t));
       }
       return ans;
    }
}

//解题思路2: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)。

class Solution {
     //用于存放每一个子集
        List<Integer> t = new ArrayList<Integer>();
         //把每一个子集放如到链表中
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
    public List<List<Integer>> subsets(int[] nums) {
        //我们从第一位开始,其实这递归的逆用,从最大子集找递归到最小子集
        dfs(0,nums);
        return ans;
    }
    public void dfs(int cur,int[] nums){
        if(cur==nums.length){
            ans.add(new ArrayList<Integer>(t));
            return;
        }
        //表示包含当前位,进行递归
        t.add(nums[cur]);
        dfs(cur+1,nums);
        //保是不包含当前位,进行递归
        t.remove(t.size()-1);
        dfs(cur+1,nums);
    }
}
上一篇:213. 打家劫舍 II


下一篇:MySQL和MongoDB性能对比(YCSB压测)