Leetcode78. 子集(二进制模拟+dfs)
Posted !0 !
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode78. 子集(二进制模拟+dfs)相关的知识,希望对你有一定的参考价值。
题目链接:https://leetcode-cn.com/problems/subsets/
解题思路
方法一:二进制模拟
我们可以用一个数i
(
0
≤
i
≤
2
n
−
1
)
(0 \\leq i \\leq 2^n - 1)
(0≤i≤2n−1)表示一个集合,数i
的第j
位表示数组中第j
个数是否属于当前枚举的集合,如果属于加入答案。
举个例子:[1,3];那他子集的个数就为2^n
。i
的二进制表示就模拟该数组的两个数是否被选择。
i=0
,其二进制位00
,表示子集空(两个数都不选)。
i=1
,其二进制为01
,表示子集[3]
(选择第二个元素,不选第一个元素)
i=2
,其二进制为10
,表示子集[1]
(选择第一个元素,不选第二个元素)
i=3
,其二进制为11
,表示子集[1,3]
(两个元素都选)
代码
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
for(int i = 0; i < 1 << nums.length; i++) { //i从0~2^n - 1
List<Integer> res = new ArrayList<>();
for(int j = 0; j < nums.length; j++) { //判断每一位是否属于当前集合
if((i >> j & 1) == 1) //如果是1则属于该集合
res.add(nums[j]);
}
ans.add(res);
}
return ans;
}
}
复杂度分析
- 时间复杂度: O ( 2 n ∗ n ) O(2^n * n) O(2n∗n)
- 空间复杂度: O ( n ) O(n) O(n)
方法二:dfs
对于数组中的每个数,我们都有选和不选两种状态,所以直接递归,枚举出所有数的这两种状态,最后组合在一起就是答案。
代码
class Solution {
List<Integer> t = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> subsets(int[] nums) {
dfs(0, nums); //从第0个元素开始
return ans;
}
public void dfs(int cur, int[] nums) {
if (cur == nums.length) { //如果枚举完所有元素
ans.add(new ArrayList<Integer>(t));
return;
}
t.add(nums[cur]); //选当前元素
dfs(cur + 1, nums); //继续递归
t.remove(t.size() - 1); //如果不选当前元素
dfs(cur + 1, nums); //继续递归
}
}
复杂度分析
- 时间复杂度: O ( 2 n ∗ n ) O(2^n * n) O(2n∗n)
- 空间复杂度: O ( n ) O(n) O(n)
以上是关于Leetcode78. 子集(二进制模拟+dfs)的主要内容,如果未能解决你的问题,请参考以下文章