markdown复制## 1. 问题背景与核心挑战
LeetCode上的子集问题(Subsets)是算法学习中的经典例题,要求给定一个不含重复元素的整数数组,返回所有可能的子集。这个问题看似简单,却蕴含着丰富的解题思路,特别适合用来对比不同算法范式的实现差异。在实际面试中,微软、谷歌等公司都曾多次考察该问题的变种。
为什么子集问题如此重要?因为它同时涉及:
- 组合数学中的幂集概念(集合所有子集的集合)
- 位运算的巧妙应用
- 回溯算法的标准实现模板
- 迭代解法的构建思路
## 2. 位运算解法精讲
### 2.1 核心思路解析
当数组长度为n时,子集总数正好是2^n个。这个特性与二进制数的位模式完美对应——每个子集可以看作一个n位二进制数,某位为1表示包含对应元素,为0则不包含。
例如数组[1,2,3]:
- 000 → []
- 001 → [3]
- 010 → [2]
- 011 → [2,3]
- ...
- 111 → [1,2,3]
### 2.2 Java实现代码
```java
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
int n = nums.length;
for (int mask = 0; mask < (1 << n); mask++) {
List<Integer> subset = new ArrayList<>();
for (int i = 0; i < n; i++) {
if ((mask & (1 << i)) != 0) {
subset.add(nums[i]);
}
}
result.add(subset);
}
return result;
}
2.3 复杂度与适用场景
- 时间复杂度:O(n * 2^n) —— 外层循环2^n次,内层循环n次
- 空间复杂度:O(n) —— 不考虑结果存储空间
- 最佳场景:当n较小(通常≤20)时效率最高,