每天一道编程题

43 阅读2分钟

LCR 079. 子集

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

解答:

方法一:递归+回溯

求组合,第一反应肯定是递归+回溯。问题就在怎么去构建递归和回溯,假设数组长度为n。求子集就是求出元素个数从0-n的所有不重复的组合个数。因为不能重复,简单起见,用一个set集合存储了所有的子集,最后再把set集合里面的数据放到List中再返回。遍历每种子集可能个数的情况,求出该元素个数下的子集。(这个方法虽然能过但是复杂度较高)

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        int n=nums.length;
        Set<List<Integer>> res=new HashSet<>();

        for(int i=0;i<=n;i++){
            backTrack(nums,0,i,new ArrayList<Integer>(),res);
        }
        List<List<Integer>> result=new ArrayList<>();
        for(List<Integer> ls:res){
            result.add(ls);
        }
        return result;
        

    }
    public void backTrack(int[] nums, int index, int n, List<Integer> ls, Set<List<Integer>> res){
        if(ls.size()==n){
            res.add(new ArrayList<>(ls));
            return;
        }
        if(index>=nums.length)
            return;
        
        ls.add(nums[index]);
        backTrack(nums, index+1, n, ls, res);
        ls.remove(ls.size()-1);

        backTrack(nums,index+1,n, ls,res);
        
    }
}

方法二:改进版本

太久没写回溯的题目了,写的好冗余啊,想得太复杂了,直接从第0个元素开始,往下添加或不添加这个元素进子集就可以了。因为每个元素值都是互不相同的。

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
        int n=nums.length;
        List<List<Integer>> res=new ArrayList<>();
        backTrack(nums,0,new ArrayList<Integer>(), res);
        return res;

    }
    public void backTrack(int[] nums, int index,  List<Integer> ls, List<List<Integer>> res){
        res.add(new ArrayList<>(ls));
        if(index>=nums.length)
            return;
        
        for(int i=index;i<nums.length;i++){
            ls.add(nums[i]);
            backTrack(nums,i+1,ls,res);
            ls.remove(ls.size()-1);
        }
        
    }
}