求数组的所有子集

比如有数组[1, 2, 3],其元素数量n = 3,将那么其子集为

[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

可以用一共三个方法来求出所有子集,以这题作为参考

1.使用二叉树来构建含有子集的叶子节点,然后使用中序遍历

思路

每一层代表一个元素,左子树代表不使用该节点,右子树代表使用该节点,使用中序遍历来获得全部叶子结点,那么就能获得该数组的子集。

思路图

在这里插入图片描述

private void getArr(List<Integer> list, List<List<Integer>> result, List<Integer> temp, int level)
    {
        if(level == list.size())
        {
            result.add(temp);
        }
        else
        {
            getArr(list, result, new ArrayList<>(temp), level + 1);
            temp.add(list.get(level));
            getArr(list, result, new ArrayList<>(temp), level + 1);
        }
    }

2.使用本质递归法递归遍历

思路

因为这个可以划分出比原问题规模小却同质的问题,那么是可以用递归解决的

private List<List<Integer>> getArr(List<Integer> list, List<List<Integer>> result, int index)
    {
        if(index == list.size())
        {
            result.add(new ArrayList<>());
        }
        else
        {
            List<List<Integer>> arr = new ArrayList<>(getArr(list, result, index + 1));
            for(List<Integer> eList : arr)
            {
                List<Integer> temp = new ArrayList<Integer>(eList);
                temp.add(list.get(index));
                //给子集的每个数组从小到大排序
                temp.sort(Comparator.comparing(Integer::intValue));
                result.add(temp);
            }
        }
        return result;
    }

3.使用二进制组合遍历

思路

这个最简单,这题有3个元素,假设这三个元素设为连续的二进制数,1代表选取,0代表不选取,从000 - 111一共有八种情况,也是子集的数量。

private void getArr(List<Integer> list, List<List<Integer>> result)
{
	//子集的数量
    int n = 1 << list.size();
    List<Integer> temp = null;
    for(int i = 0; i < n; i ++)
    {
        temp = new ArrayList<>();
        int j = i;
        int index = list.size() - 1;
        //循环前检测j是否是000
        while(j > 0)
        {
            if((j&1) == 1)
            {
                temp.add(list.get(index));
            }
            j = j >> 1;
            index --;
        }
        temp.sort(Comparator.comparing(Integer::intValue));
        result.add(temp);
    }
}

经过测试,对于包含元素数量20左右的数组的所有子集,三种方法处理速度都到了1.5-1.8秒左右,到了25之后速度急剧下降,10秒钟也没有结果,因为这三个算法时间复杂度都是O(2^n)级别的

三个算法的思路是参考了这个大佬的博客:
Leetcode:Subsets 求数组的所有子集

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值