Leetcode78. Subsets

Leetcode78. Subsets

Given a set of distinct integers, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.

Example:

Input: nums = [1,2,3]
Output:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

解法一 迭代一

找出数组长度 1 的所有解,然后再在长度为 1 的所有解上加 1 个数字变成长度为 2 的所有解,同样的直到 n。
在这里插入图片描述

public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> res = new ArrayList<List<Integer>>(); 
    List<List<Integer>> ans = new ArrayList<List<Integer>>();
    ans.add(new ArrayList<Integer>());
    res.add(new ArrayList<Integer>());
    int n = nums.length;
    // 第一层循环,子数组长度从 1 到 n
    for (int i = 1; i <= n; i++) {
        // 第二层循环,遍历上次的所有结果
        List<List<Integer>> tmp = new ArrayList<List<Integer>>();
        for (List<Integer> list : res) {
            // 第三次循环,对每个结果进行扩展
            for (int m = 0; m < n; m++) {
                //只添加比末尾数字大的数字,防止重复
                if (list.size() > 0 && list.get(list.size() - 1) >= nums[m])
                    continue;
                List<Integer> newList = new ArrayList<Integer>(list);
                newList.add(nums[m]);
                tmp.add(newList);
                ans.add(newList);
            }
        }
        res = tmp;
    }
    return ans;
}

解法二 迭代二

从条件上入手,先只考虑给定数组的 1 个元素的所有子数组,然后再考虑数组的 2 个元素的所有子数组 … 最后再考虑数组的 n 个元素的所有子数组。求 k 个元素的所有子数组,只需要在 k - 1 个元素的所有子数组里边加上 nums [ k ] 即可。

在这里插入图片描述

public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> ans = new ArrayList<>();
    ans.add(new ArrayList<>());//初始化空数组
    for(int i = 0;i<nums.length;i++){
        List<List<Integer>> ans_tmp = new ArrayList<>();
        //遍历之前的所有结果
        for(List<Integer> list : ans){
            List<Integer> tmp = new ArrayList<>(list);
            tmp.add(nums[i]); //加入新增数字
            ans_tmp.add(tmp);
        }
        ans.addAll(ans_tmp);
    }
    return ans;
}

解法三 回溯

在这里插入图片描述

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

private void getAns(int[] nums, int start, ArrayList<Integer> temp, List<List<Integer>> ans) { 
    ans.add(new ArrayList<>(temp));
    for (int i = start; i < nums.length; i++) {
        temp.add(nums[i]);
        getAns(nums, i + 1, temp, ans);
        temp.remove(temp.size() - 1);
    }
}

解法四 使用位掩码

数组的每个元素,可以有两个状态:
1、不在子数组中(用 00 表示);
2、在子数组中(用 11 表示)。

从 0 到 2 的数组个数次幂(不包括)的整数的二进制表示就能表示所有状态的组合。
在这里插入图片描述

public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> ans = new ArrayList<>();
    int bit_nums = nums.length;
    int ans_nums = 1 << bit_nums; //执行 2 的 n 次方
    for (int i = 0; i < ans_nums; i++) {
        List<Integer> tmp = new ArrayList<>();
        int count = 0; //记录当前对应数组的哪一位
        int i_copy = i; //用来移位
        while (i_copy != 0) { 
            if ((i_copy & 1) == 1) { //判断当前位是否是 1
                tmp.add(nums[count]);
            }
            count++;
            i_copy = i_copy >> 1;//右移一位
        }
        ans.add(tmp);

    }
    return ans;
}
Python
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        size = len(nums)
        n = 1 << size
        res = []
        for i in range(n):
            cur = []
            for j in range(size):
                if i >> j & 1:
                    cur.append(nums[j])
            res.append(cur)
        return res
发布了82 篇原创文章 · 获赞 7 · 访问量 5006

猜你喜欢

转载自blog.csdn.net/magic_jiayu/article/details/104258026
今日推荐