Open azl397985856 opened 2 years ago
/**
* @param {number[]} nums
* @return {number[][]}
*/
const subsets = function(nums) {
const results = [];
search(nums, 0, [], results);
return results;
};
function search(nums, start, path, results) {
results.push(path.slice(0));
for (let i = start; i < nums.length; i++) {
path.push(nums[i]);
search(nums, i + 1, path, results);
path.pop(); // backtrack
}
}
回溯。
class Solution {
public:
vector<int> t;
vector<vector<int>> ans;
void dfs(int cur, vector<int>& nums) {
if (cur == nums.size()) {
ans.push_back(t);
return;
}
t.push_back(nums[cur]);
dfs(cur + 1, nums);
t.pop_back();
dfs(cur + 1, nums);
}
vector<vector<int>> subsets(vector<int>& nums) {
dfs(0, nums);
return ans;
}
};
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
result=[]
subset=[]
def dfs(i):
if i >=len(nums):
return result.append(subset.copy())
subset.append(nums[i])
dfs(i+1)
subset.pop()
dfs(i+1)
dfs(0)
return result
Time: O(n *2^n)
Space: O(n)
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
if not nums:
return
res = []
def dfs(i, subset):
res.append(subset)
for j in range(i, len(nums)):
dfs(j + 1, subset + [nums[j]])
dfs(0, [])
return res
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
int N = nums.size();
vector<vector<int>> res;
int all_states = 1 << N; //2^n
for(int i=0; i<all_states; i++)
{
vector<int> temp;
for(int j=0; j < N; j++)
{
if((i & (1<<j)))
temp.push_back(nums[j]);
}
res.push_back(temp);
}
return res;
}
};
Space:O(n x 2^n) Time:O(n x 2^n)
var subsets = function(nums) {
let result = []
let path = []
function backtracking(startIndex) {
result.push(path.slice())
for(let i = startIndex; i < nums.length; i++) {
path.push(nums[i])
backtracking(i + 1)
path.pop()
}
}
backtracking(0)
return result
};
class Solution {
List<Integer> t = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> subsets(int[] nums) {
int n = nums.length;
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
for (int i = 0; i < n; ++i) {
if ((mask & (1 << i)) != 0) {
t.add(nums[i]);
}
}
ans.add(new ArrayList<Integer>(t));
}
return ans;
}
}
Solution 2:
class Solution {
private:
vector<vector<int>> res;
vector<int> level;
public:
vector<vector<int>> subsets(vector<int>& nums) {
dfs(0, nums);
return res;
}
void dfs(int n, vector<int>& nums) {
if (n >= nums.size()) {
res.push_back(level);
return ;
}
for (int i = 0; i < 2; i++) {
if (i == 0)
level.push_back(nums[n]);
dfs(n + 1, nums);
if (i == 0)
level.pop_back();
}
return ;
}
};
枚举
/**
* @param {number[]} nums
* @return {number[][]}
*/
var subsets = function (nums) {
const ans = []
const n = nums.length
for (let mask = 0; mask < (1 << n); ++mask) {
const tp = []
for (let i = 0; i < n; ++i) if (mask & (1 << i)) tp.push(nums[i])
ans.push(tp)
}
return ans
};
时间复杂度 O(n2^n)
空间复杂度 O(n)
思路:回溯
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
List<Integer> tmp = new ArrayList<>();
Arrays.sort(nums);
backtrack(res, tmp, nums, 0);
return res;
}
private void backtrack(List<List<Integer>> res, List<Integer> tmp, int[] nums, int start){
//走过的所有路径都是子集的一部分,所以都要加入到集合中
res.add(new ArrayList<>(tmp));
for(int i = start; i < nums.length; i++){
//做出选择
tmp.add(nums[i]);
//递归
backtrack(res, tmp, nums, i + 1);
//撤销选择
tmp.remove(tmp.size() - 1);
}
}
}
时间复杂度:O(N * 2 ^ N) 空间复杂度:O(N)
class Solution {
List<List<Integer>> res = new ArrayList<>();
int[] arr;
public List<List<Integer>> subsets(int[] nums) {
arr = nums;
List<Integer> list = new ArrayList<>(nums.length);
res.add(new ArrayList(list));
dfs(0,list);
return res;
}
//dfs
private void dfs(int now,List<Integer> list){
for(int i=0;i+now<arr.length;i++){
list.add(arr[i+now]);
res.add(new ArrayList(list));
dfs(i+now+1,list);
list.remove(list.size()-1);
}
}
}
class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: """ iterative """ end_num = 2 ** len(nums) results = [] for k in range(end_num): single_solution = [] for i in range(len(nums)): if (k >> i) & 1 == 1: single_solution.append(nums[i]) results.append(single_solution) return results
迭代: res=[[]]\ i=1时,res=[[],[1]]\ i=2时,res=[[],[1],[2],[2,1]]\ i=3时,res=[[],[1],[2],[2,1],[3],[3,1],[3,2],[3,2,1]] 迭代完毕
这里使用了powcai大神的代码
Python3 Code:
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res=[[]]
for i in nums:
for num in res:
res=res+[[i]+num]
return res
直接利用循环,每次加一个数
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res=[[]]
path=[]
for i in range(len(nums)-1,-1,-1):
m=len(res)
for j in range(m):
res.append([nums[i]]+res[j])
return res
先打卡
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res=[[]]
for i in nums:
for num in res:
res=res+[[i]+num]
return res
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res;
int len = 1 << nums.size();
for (int mask = 0; mask < len; ++mask){
vector<int> t;
for (int n = 0; n < nums.size(); ++n){
if (mask & (1 << n)) {
t.push_back(nums[n]);
}
}
res.push_back(t);
}
return res;
}
【Day 72】78. 子集
https://leetcode-cn.com/problems/subsets/
位运算:
class Solution:
def subsets(self, nums):
res, end = [], 1 << len(nums)
for sign in range(end):
subset = []
for i in range(len(nums)):
if ((1 << i) & sign) != 0: #用第 i 位是 1 比特与当前 sign 相与,若结果不为 0 就代表第 i 位比是 1
subset.append(nums[i])
res.append(subset)
return res
bfs:这个最快28ms
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res=[[]]
for i in nums:
for num in res:
res=res+[[i]+num]
return res
dfs
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
n = len(nums)
def dfs(i, tmp):
res.append(tmp)
for j in range(i, n):
dfs(j + 1,tmp + [nums[j]] )
dfs(0, [])
return res
时间复杂度:O(n*2^n)一共 2^n 个状态,每种状态需要 O(n)的时间来构造子集
空间复杂度:O(n)
class Solution {
public List<List<Integer>> subsets(int[] nums) {
int length = nums.length;
List<List<Integer>> res = new ArrayList<>();
for(int i = 0; i <= Math.pow(2, length) - 1; i++) {
List<Integer> tmp = new ArrayList<>();
for(int j = 0; j < length; j ++) {
if(((1 << j) & i) != 0) {
tmp.add(nums[j]);
}
}
res.add(tmp);
}
return res;
}
}
python内置函数
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = [[], ]
for i in range(1, len(nums) + 1):
for tup in combinations(nums, i):
res.append(list(tup))
return res
func subsets(nums []int) (ans [][]int) {
set := []int{}
var dfs func(int)
dfs = func(cur int) {
if cur == len(nums) {
ans = append(ans, append([]int(nil), set...))
return
}
set = append(set, nums[cur])
dfs(cur + 1)
set = set[:len(set)-1]
dfs(cur + 1)
}
dfs(0)
return
}
思路 用二进制的位作为选取的值 代码(C++)
实现语言: C++
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
const int n = nums.size();
vector<vector<int>> res;
for (int s = 0; s < (1 << n); s++)
{ /* s表示一个状态state, 相当于取位 */
vector<int> curSet;
for (int i = 0; i < n; i++)
if ((s & (1 << i)) > 0)
curSet.push_back(nums[i]);
res.push_back(curSet);
}
return res;
}
};
复杂度分析 时间复杂度: O(N 2^N) 空间复杂度: O(N 2^N)
class Solution {
List<Integer> t = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> subsets(int[] nums) {
int n = nums.length;
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
for (int i = 0; i < n; ++i) {
if ((mask & (1 << i)) != 0) {
t.add(nums[i]);
}
}
ans.add(new ArrayList<Integer>(t));
}
return ans;
}
}
var subsets = function(nums) {
const t = [];
const ans = [];
const n = nums.length;
const dfs = (cur) => {
if (cur === nums.length) {
ans.push(t.slice());
return;
}
t.push(nums[cur]);
dfs(cur + 1, nums);
t.pop(t.length - 1);
dfs(cur + 1, nums);
}
dfs(0, nums);
return ans;
}
时间:O(n * 2^n) 空间:O(n)
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
def dfs(start, nums, path):
res.append(path[:])
for i in range(start,len(nums)):
path.append(nums[i])
dfs(i+1,nums,path)
path.pop()
res = []
dfs(0,nums,[])
return res
class Solution: def subsets(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ res, end = [], 1 << len(nums) for sign in range(end): subset = [] for i in range(len(nums)): if ((1 << i) & sign) != 0: subset.append(nums[i]) res.append(subset) return res
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
self.dfs(nums, 0, [], res)
return res
def dfs(self, nums, index, path, res):
res.append(path)
for i in range(index, len(nums)):
self.dfs(nums, i + 1, path + [nums[i]], res)
Time Complexity: O(n * 2^n), Space Complexity: O(n)
位运算
class Solution {
List<Integer> t = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> subsets(int[] nums) {
int n = nums.length;
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
for (int i = 0; i < n; ++i) {
if ((mask & (1 << i)) != 0) {
t.add(nums[i]);
}
}
ans.add(new ArrayList<Integer>(t));
}
return ans;
}
}
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
n = 1<<len(nums)
ans = []
for i in range(n):
subset = []
for j in range(len(nums)):
if ((1 << j) & i) != 0:
subset.append(nums[j])
ans.append(subset)
return ans
vector<vector<int>> subsets(vector<int>& nums) {
int len = 1 << nums.size();
vector<vector<int>> res;
for(int i = 0; i < len; i++)
{
vector<int> single;
for(int j = 0; j < nums.size(); j++)
// for(int j = 0; i >> j > 0; j++)
{
if ((i >> j) & 1 == 1)
single.push_back(nums[j]);
}
res.push_back(single);
}
return res;
}
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
sub = []
def backtrack(i):
if i >= len(nums):
res.append(sub.copy())
return
sub.append(nums[i])
backtrack(i+1)
sub.pop()
backtrack(i+1)
backtrack(0)
return res
var subsets = function(nums) {
const path = [],res = [];
const treeBack = (startIndex)=>{
res.push([...path]);
for(let i = startIndex ;i<nums.length;i++){
path.push(nums[i]);
treeBack(i+1);
path.pop();
}
}
treeBack(0);
return res;
};
python
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
self.dfs(nums, [], res)
return res
def dfs(self, nums, track, res):
res.append(track)
for i in range(len(nums)):
self.dfs(nums[i + 1:], track + [nums[i]], res)
backtracking,todo:位运算
class Solution {
public:
vector<int> cur;
vector<vector<int>> res;
void dfs(int curr, vector<int>& nums) {
if (curr == nums.size()) {
res.push_back(cur);
return;
}
cur.push_back(nums[curr]);
dfs(curr + 1, nums);
cur.pop_back();
dfs(curr + 1, nums);
}
vector<vector<int>> subsets(vector<int>& nums) {
dfs(0, nums);
return res;
}
};
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new LinkedList<>();
generateRes(res, new ArrayList<>(), nums, 0);
return res;
}
private void generateRes(List<List<Integer>> res, List<Integer> cur, int[] nums, int index) {
if (index == nums.length) {
res.add(new ArrayList<>(cur));
return;
}
cur.add(nums[index]);
generateRes(res, cur, nums, index + 1);
cur.remove(cur.size() - 1);
generateRes(res, cur, nums, index + 1);
}
}
time : O(2^n) space O(n)
javascript
/*
* @lc app=leetcode.cn id=78 lang=javascript
*
* [78] 子集
*/
// @lc code=start
/**
* @param {number[]} nums
* @return {number[][]}
*/
var subsets = function(nums) {
const powerset = []
generatePowerset([], 0)
function generatePowerset(path, index) {
powerset.push(path)
for (let i = index; i < nums.length; i++) {
generatePowerset([...path, nums[i]], i + 1)
}
}
return powerset
};
// @lc code=end
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
size = len(nums)
n = 1 << size
res = []
for i in range(n):
cur = []
for j in range(size):
if i >> j & 1:
cur.append(nums[j])
res.append(cur)
return res
数组中的元素互不相同.
使用位运算, 在二进制状态下做状态的轮流变换(1表示选中, 0表示不选中).
java
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<Integer> list = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
int n = nums.length;
for (int mask = 0; mask < (1 << n); ++mask) {
list.clear();
for (int i = 0; i < n; i++) {
if ((mask & (1 << i)) != 0) {
list.add(nums[i]);
}
}
ans.add(new ArrayList<Integer>(list));
}
return ans;
}
}
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res, end = [], 1 << len(nums)
for sign in range(end):
subset = []
for i in range(len(nums)):
if ((1 << i) & sign) != 0:
subset.append(nums[i])
res.append(subset)
return res
时间复杂度:O(n*2^n) 空间复杂度:O(n)
回溯:
回溯函数的判断语句前加入添加语句,每个合法的组合都添加到 ansans; 每次回溯时 startIndexstartIndex 都为当前 index + 1index+1, 保证不会回头取重复组合.
class Solution {
List<List<Integer>> ans = new LinkedList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsets(int[] nums) {
int len = nums.length;
backtrack(0, nums, len);
return ans;
}
private void backtrack(int startIndex, int[] nums, int len){
ans.add(new LinkedList<>(path));
if(startIndex == len) return;
for (int i = startIndex; i < len; i++){
path.add(nums[i]);
backtrack(i + 1, nums, len);
path.removeLast();
}
}
}
class Solution {
List<Integer> t = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> subsets(int[] nums) {
int n = nums.length;
for (int mask = 0; mask < (1 << n); ++mask) {
t.clear();
for (int i = 0; i < n; ++i) {
if ((mask & (1 << i)) != 0) {
t.add(nums[i]);
}
}
ans.add(new ArrayList<Integer>(t));
}
return ans;
}
}
排列组合
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
for i in range(len(nums)+1):
for tmp in itertools.combinations(nums, i):
res.append(tmp)
return res
思路:通过位运算的方式,
class Solution { public List<List<Integer>> subsets(int[] nums) { int t =0; List<List<Integer>> list = new ArrayList<>(); int tar =(int)Math.pow(2,nums.length); while(t<tar){ list.add(fun(nums,t)); t++; } return list; } public List<Integer> fun(int[]nums,int target){ String t = Integer.toBinaryString(target); int size = t.length()-1; List<Integer> res = new ArrayList<>(); for(int i=0;i<t.length();i++){ if(t.charAt(i)=='1'){ res.add(nums[size-i]); } } return res; } }
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res, end = [], 1 << len(nums)
for n in range(end):
subset = []
for i in range(len(nums)):
if (1 << i) & n != 0:
subset.append(nums[i])
res.append(subset)
return res
Time complexity: O(N * 2^N)
Space complexity: O(N) the longest subset is size N
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
path = []
def backtrack(nums,startIndex):
res.append(path[:]) #收集子集,要放在终止添加的上面,否则会漏掉自己
for i in range(startIndex,len(nums)): #当startIndex已经大于数组的长度了,就终止了,for循环本来也结束了,所以不需要终止条件
path.append(nums[i])
backtrack(nums,i+1) #递归
path.pop() #回溯
backtrack(nums,0)
return res
O(N*2^N)
O(N*2^N)
class Solution {
public List<List<Integer>> subsets1(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
generate(res, nums, 0, new ArrayList<>());
return res;
}
// [1,2,3]
//[].
// [1], [1,2], [1,2,3]
// [2], [2,3]
// [3]
private void generate(List<List<Integer>> res, int[] nums, int curIndex, List<Integer> status) {
res.add(new ArrayList<>(status));
for (int start = curIndex; start < nums.length; start++) {
status.add(nums[start]);
generate(res, nums, start + 1, status);
status.remove(status.size() - 1);
}
}
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
int start = 0, end = 1 << nums.length;
for (int sign = start; sign < end; sign++) {
List<Integer> status = new ArrayList<>();
for (int pos = 0; pos < nums.length; pos++) {
if (((1 << pos) & sign) != 0) {
status.add(nums[pos]);
}
}
res.add(status);
}
return res;
}
}
位运算
JavaScript Code
ar subsets = function (nums) {
const ans = [];
const n = nums.length;
for (let mask = 0; mask < 1 << n; ++mask) {
const t = [];
for (let i = 0; i < n; ++i) {
if (mask & (1 << i)) {
t.push(nums[i]);
}
}
ans.push(t);
}
return ans;
};
复杂度
令 N 为数组长度
C++ Code:
class Solution {
public:
vector<vector<int>> res;
unordered_map<int,int> mp;
void dfs(vector<int>& nums,int dp, vector<int> temp)
{
if(mp.count(dp)==1)
return;
res.push_back(temp);
mp[dp]=1;
for(int i=0;i<nums.size();i++)
{
temp.push_back(nums[i]);
dfs(nums,dp|(1<<i),temp);
temp.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
dfs(nums,0,{});
return res;
}
};
class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: """ iterative """ end_num = 2 ** len(nums) results = [] for k in range(end_num): single_solution = [] for i in range(len(nums)): if (k >> i) & 1 == 1: single_solution.append(nums[i]) results.append(single_solution) return results
78. 子集
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/subsets/
前置知识
题目描述
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]] 示例 2:
输入:nums = [0] 输出:[[],[0]]
提示:
1 <= nums.length <= 10 -10 <= nums[i] <= 10 nums 中的所有元素 互不相同