leetcode 数组—幂集

幂集。编写一种方法,返回某集合的所有子集。集合中不包含重复的元素。
说明:解集不能包含重复的子集。

示例:

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

题解:

思路一:二进制法

首先知道n个元素的集合的幂集个数为: n^2
nums = [1,2,3], 长度为3, 对于nums[]的位置,取值赋1,不取赋0。
如:
第0个子集: 0->[0,0,0]: []
第1个子集: 1->[0,0,1]: [nums[0]]
第2个子集: 2->[0,1,0]: [nums[1]]
第3个子集: 3->[0, 1, 1]: [nums[0],nums[1]]
第4个子集: 4->[1, 0, 0]: [nums[2]]
第5个子集: 5->[1, 0, 1]:[nums[0],nums[2]]
第6个子集: 6->[1, 1, 0]:[nums[1],nums[2]]
第7个子集: 7->[1, 1, 1]:[nums[0],nums[1],nums[2]]


JAVA代码:

class Solution {
        public List<List<Integer>> subsets(int[] nums) {
            // n个元素的集合,幂集个数为2^n
            
            List<List<Integer>> res = new ArrayList<>();
            int n = nums.length;
            //i代表第i个集合
            for (int i=0; i<(1<<n); i++){
                List<Integer> temp = new ArrayList<>();
				//j代表Nums[]的位置
                for(int j=0; j<n; j++){
                    if ((i & (1<<j))!=0) {
                        temp.add(nums[j]);
                    }
                }
                res.add(temp);
            }
            return res;
    }
}

思路二:枚举法

Nums = [1,2,3]
在这里插入图片描述
JAVA代码如下

class Solution {
        public List<List<Integer>> subsets1(int[] nums) {
            List<List<Integer>> output = new ArrayList<>();
            //初始时output中只有一个空的list
            output.add(new ArrayList<>());

            for (int num: nums){
                List<List<Integer>> newSubsets = new ArrayList<>(); //存放每加入一个新元素后新增的子集

                //产生新的子集
                for (List<Integer> curr1: output) {
                    newSubsets.add(new ArrayList<Integer>(curr1){{add(num);}});  //这一句不是太懂
                }
                //将新子集加入到output中
                for (List<Integer> curr2: newSubsets)
                    output.add(curr2);
            }
            return output;
        }
    }

思路三:二叉树法

所有子集可构成一棵满二叉树,左右子树看作选和不选的问题,每一层则表示对第i个元素的选与不选。那么只要遍历这棵满二叉树即可。
在这里插入图片描述
JAVA代码:

    public static void preOrder(List<List<Integer>> res, List<Integer> subset, int i, int[] nums){
        if (i>=nums.length) return;
        // 到了新的状态,记录新的路径,要重新拷贝一份
        subset = new ArrayList<Integer>(subset);

        res.add(subset);
        preOrder(res, subset, i+1, nums);
        subset.add(nums[i]);
        preOrder(res, subset, i+1, nums);
    }
思路四:回溯法

在这里插入图片描述
JAVA代码:

    public static void backtrack(int[] nums, int i, List<Integer> sub, List<List<Integer>> res) {
        for (int j = i; j < nums.length; j++) {
            sub.add(nums[j]);
            res.add(new ArrayList<Integer>(sub));
            backtrack(nums, j + 1, sub, res);
            sub.remove(sub.size() - 1);
        }
    }
发布了9 篇原创文章 · 获赞 0 · 访问量 257

猜你喜欢

转载自blog.csdn.net/powerful_ren/article/details/104616594