Solution 1
使用DFS回溯,比较传统的做法。
- 时间复杂度: O ( N × 2 N ) O( N \times 2^N ) O(N×2N),其中 N N N即为输入数字列表的长度,决策树的分枝有 2 N 2^N 2N个,每一个分支遍历完成需要到达深度 N N N
- 空间复杂度: O ( N ) O(N) O(N),一次只需要保存最多全部数组,回溯的资源消耗与树最大深度一致
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ans;
vector<int> current;
int numLen = nums.size();
for (int i = 0; i <= numLen; i++) {
this->dfs(ans, nums, current, 0, i);
}
return ans;
}
private:
void dfs(vector<vector<int>> & ans, vector<int> & nums, vector<int> & current, int pos, int numLen) {
// this->print("DFS", current);
if (current.size() == numLen) {
// this->print("OUTPUT", current);
ans.push_back(current);
return;
}
for (int i = pos; i < nums.size(); ++i) {
current.push_back(nums[i]);
this->dfs(ans, nums, current, i + 1, numLen);
current.pop_back();
}
}
void print(string input, vector<int> & test) {
cout << input << " ";
for (auto item: test) {
cout << item << " ";
}
cout << endl;
}
};
Solution 2 【官方题解】
二进制排序,利用二进制数的字典序枚举作为所有数字的选择状态,从而表示所有的子集情况。即用0表示没添加,1表示添加,从00000到11111的所有枚举就是所有可能的子集选择情况。
主要的实现问题就是如果保存带有前导零的二进制串。
貌似这种方法面试时的时候用比较漂亮?实际上没有优化,只是将问题简化了。
- 时间复杂度: O ( N × 2 N ) O( N \times 2^N ) O(N×2N),其中 N N N即为输入数字列表的长度,决策树的分枝有 2 N 2^N 2N个,每一个分支遍历完成需要到达深度 N N N
- 空间复杂度: O ( N × 2 N ) O( N \times 2^N ) O(N×2N),与回溯方法不同的存储逻辑导致占用较高
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> ans;
int numLen = nums.size();
auto masks = this->bitmask(numLen);
for (auto mask: masks) {
vector<int> temp;
for (int i = 0; i < numLen; ++i) {
if (mask[i] == '1') {
temp.push_back(nums[i]);
}
}
ans.push_back(temp);
}
return ans;
}
private:
vector<string> bitmask(int numLen) {
vector<string> bitmasks;
for (int i = 0; i < pow(2, numLen); ++i) {
bitset<11> bit(i); // 最多10位长度
bitmasks.push_back(bit.to_string().substr(11 - numLen));
}
return bitmasks;
}
void print(string input, vector<string> & test) {
cout << input << " ";
for (auto item: test) {
cout << item << " ";
}
cout << endl;
}
};
Solution 3
Solution 1的Python实现
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
ans, current = list(), list()
for i in range(len(nums) + 1):
self._dfs(ans, nums, current, 0, i)
return ans
def _dfs(self, ans: List[List[int]], nums: List[int], current: List[int], pos: int, numLen: int) -> None:
if len(current) == numLen:
ans.append(copy.deepcopy(current))
return
for i in range(pos, len(nums)):
current.append(nums[i])
self._dfs(ans, nums, current, i + 1, numLen)
current.pop()
Solution 4
Solution 2的Python实现
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
ans= list()
masks = self._bitmasks(len(nums))
for mask in masks:
temp = list()
for i in range(len(mask)):
if mask[i] == '1':
temp.append(nums[i])
ans.append(copy.deepcopy(temp))
return ans
def _bitmasks(self, numLen: int) -> List[str]:
masks = list()
for i in range(2**numLen) :
masks.append(bin(i)[2:].zfill(numLen))
return masks