【做题也是一场游戏】78. 子集

246 阅读1分钟

题目地址

leetcode-cn.com/problems/su…

题目描述

给你一个整数数组 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 中的所有元素 互不相同

题解

基本思想就是元素在或不在

bit位表示在或不在

由于数组长度最大只有10,可以用一个 int 表示,也可以用一个 0-1 数组表示,但是空间复杂就增加为 O(n)O(n)

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;
        for (int mask = 0; mask < (1 << n); ++mask) {
            t.clear();
            for (int i = 0; i < n; ++i) {
                if ((mask & (1 << i)) != 0) {
                    t.add(nums[i]);
                }
            }
            ans.add(new ArrayList<Integer>(t));
        }
        return ans;
    }
}

复杂度分析

  • 时间复杂度:O(n×2n)O(n \times 2^n)。一共 2n2^n 个状态,每种状态需要 O(n)O(n) 的时间来构造子集。

  • 空间复杂度:O(n)O(n)。即构造子集使用的临时数组 tt 的空间代价。

递归加回溯

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);
    }
}

复杂度分析

  • 时间复杂度:O(n×2n)O(n \times 2 ^ n)。一共 2n2^n 个状态,每种状态需要 O(n)O(n) 的时间来构造子集。
  • 空间复杂度:O(n)O(n)。临时数组 tt 的空间代价是 O(n)O(n),递归时栈空间的代价为 O(n)O(n)

直接迭代

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        result.add(new ArrayList<>());

        for (Integer num : nums) {
            int size = result.size();
            for (int i = 0; i < size; i++) {
                List<Integer> temp = new ArrayList<>(result.get(i));
                temp.add(num);
                result.add(temp);
            }
        }
        return result;
    }
}

复杂度分析

  • 时间复杂度:O(n×2n)O(n \times 2 ^ n)。一共 2n2^n 个状态,每种状态需要 O(n)O(n) 的时间来构造子集。
  • 空间复杂度:O(n)O(n)。临时数组 temptemp 的空间代价是 O(n)O(n),递归时栈空间的代价为 O(n)O(n)