菜鸡每日一题系列打卡78天
每天一道算法题目
小伙伴们一起留言打卡
坚持就是胜利,我们一起努力!
题目描述(引自LeetCode)
给定一组不含重复元素的整数数组nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
题目分析
其实这道题目和上一道题目很类似,上一题是求指定集合(1 ~ n)中的任选k个元素的组合,而本题如果按照这种说法进行描述的话,就是,求给定数组nums中任选0,1,2,……,nums.length个元素的组合。
上一题我们用回溯法解决的,这道题菜鸡将采用二进制排序的方式进行解决。所谓的二进制排序,就是将每个子集映射到长度为n的位掩码中,如果第i位掩码为1,则表示nums[i]在子集中;反之,如果第i位掩码为0,则表示nums[i]不在子集中。举个栗子:00...00表示空子集,11...11表示全集。
使用二进制排序的方法虽然时间复杂度没有本质提高,但位运算操作实际上是比回溯法的方法调用要快很多的。话不多说,上代码!
代码实现
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> result = new ArrayList();
// 快速幂求取子集个数
int n = myPow(2, nums.length);
for (int i = 0; i < n; i++) {
List<Integer> tmp = new ArrayList();
// 求取每一个i对应的子集
for (int j = 0; j < nums.length; j++) {
if (((i >> j) & 1) == 1) tmp.add(nums[j]);
}
result.add(tmp);
}
// 返回结果
return result;
}
// 快速幂
private int myPow(int x, int n) {
int tmp = 1;
while (n > 1) {
if ((n & 1) == 0) {
x *= x;
n >>= 1;
} else {
tmp *= x;
n -= 1;
}
}
return x * tmp;
}
}
代码分析
对代码进行分析,程序的循环次数为n * 2^n,因此,时间复杂度为O(n * 2^n);而就空间而言,需要存储所有的子集,因此,空间复杂度为O(n * 2^n)。
执行结果
学习 | 工作 | 分享
????长按关注“有理想的菜鸡”
只有你想不到,没有你学不到