0
点赞
收藏
分享

微信扫一扫

[LeetCode]Subsets


Question
Given a set of distinct integers, nums, return all possible subsets.

Note: The solution set must not contain duplicate subsets.

For example,
If ​​​nums = [1,2,3]​​, a solution is:

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

本题难度Medium。

【复杂度】
时间 O(N) 空间 O(N)

【思路】
与​​[LeetCode]Combinations​​的思路一样,不同点就在于:

  1. 19行,将递归过程中的preList放入结果
  2. base case仅仅判断是否到达末端

【代码】

public class Solution {
public List<List<Integer>> subsets(int[] nums) {
//require
List<List<Integer>> ans=new LinkedList<>();
ans.add(new LinkedList<Integer>()); //add [] to ans
//invariant
helper(0,new LinkedList<Integer>(),nums,ans);
//ensure
return ans;
}
private void helper(int start,List preList,int[] nums,List<List<Integer>> ans){
int size=nums.length;
//base case
if(start==size)
return;

for(int i=start;i<size;i++){
preList.add(nums[i]);
ans.add(new LinkedList(preList));
helper(i+1,preList,nums,ans);
preList.remove(preList.size()-1);
}
}
}

【注意】
​​​[]​​也是一个subSet。

follow up
我想起来Stanford的公开课《Programming Abstractions》第10集对此有讲述,她的方法更为精妙:

每次分为两种情况:
一种是包含该元素,一种是不包含该元素

一并解决了​​[]​​​也是subSet的问题。
代码:

public class Solution {
public List<List<Integer>> subsets(int[] nums) {
//require
List<List<Integer>> ans=new LinkedList<>();
//invariant
helper(0,new LinkedList<Integer>(),nums,ans);
//ensure
return ans;
}
private void helper(int start,List preList,int[] nums,List<List<Integer>> ans){
int size=nums.length;
//base case
if(start==size){
ans.add(new LinkedList(preList));
return;
}
//include nums[start]
preList.add(nums[start]);
helper(start+1,preList,nums,ans);
preList.remove(preList.size()-1);
//exclude nums[start]
helper(start+1,preList,nums,ans);
}
}

看到代码的22行会有点奇怪:为什么它后面没有​​preList.remove(preList.size()-1);​​​。(长期做recursition的职业病)能这样做的原因就在于:向右遍历时并不破坏初始状态。比如:
集合为:abcd
当preList=“abc”时,preList在遍历树中是这样的:

|
第n级 abc
| |
第n+1级 abcd abc

由第n级向第n+1级时,先下到左边,​​preList=“abcd”​​​,然后递归回第n级时,删掉​​'d'​​​,preList又变回​​"abc"​​,然后再下到右边preList不变,然后递归回第n级,preList仍为初始状态。


举报

相关推荐

0 条评论