17.Subsets-子集(中等题)

子集

  1. 题目

    给定一个含不同整数的集合,返回其所有的子集

    注意事项
    子集中的元素排列必须是非降序的,解集必须不包含重复的子集

  2. 样例

    如果 S = [1,2,3],有如下的解:
    这里写图片描述

  3. 挑战

    你可以同时用递归与非递归的方式解决么?

  4. 题解

1.递归法

先对数组排序,然后回溯递归。下图是以样例画的很粗糙的递归堆栈图,对着代码推算一遍就明白了。
这里写图片描述

class Solution {
    /**
     * @param S: A set of numbers.
     * @return: A list of lists. All valid subsets.
     */
    public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        ArrayList<Integer> list = new ArrayList<Integer>();
        Arrays.sort(nums);  
        subsetsHelper(result, list, nums, 0);

        return result;
    }

    private void subsetsHelper(ArrayList<ArrayList<Integer>> result,
        ArrayList<Integer> list, int[] nums, int pos)
    {
        result.add(new ArrayList<Integer>(list));
        for (int i=pos;i<nums.length;i++)
        {
            list.add(nums[i]);
            subsetsHelper(result,list,nums,i+1);
            list.remove(list.size()-1);
        }
    }
}

2.非递归法

我们还是以[1,2,3]为例进行如下分析:
0x000->[];
0x001->[1];
0x010->[2];

0x111->[1,2,3];
也就是每一个子集都对应[0,2^n-1]中的一个二进制。

class Solution {
    /**
     * @param S: A set of numbers.
     * @return: A list of lists. All valid subsets.
     */
    public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        int n = nums.length;
        Arrays.sort(nums);
        for (int i=0;i<(1<<n);i++)
        {
            ArrayList<Integer> list = new ArrayList<Integer>();
            for (int j=0;j<n;j++)
            {
                if ((i&(1<<j)) != 0)
                {
                    list.add(nums[j]);
                }
            }
            result.add(list);
        }
        return result;
    }
}

Last Update 2016.9.24

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值