[C++]LeetCode: 63 Subsets
2014-12-30 21:13
435 查看
题目:
Given a set of distinct integers, S, return all possible subsets.
Note:
Elements in a subset must be in non-descending order.
The solution set must not contain duplicate subsets.
For example,
If S =
Answer 1 :
DFS方法
思路解析:求集合的所有子集的问题。题目要求子集中元素非递减排列。因此,首先要对原来的集合排序。
原来的集合中的每一个元素在子集中只有两种状态:要么存在,要么不存在。这样构造子集的过程中每个元素就有两种选择方法,选择、不选择。因此可以构造一个二叉树,例如对例子中集合{1,2,3}构造的二叉树如下{左子树表示选择该层处理的元素,右子树表示不选择},最后得到的叶子结点就是要求的子集。
Attention:
1. 通过原来的集合的元素总数,判断是否到达叶子结点。
AC Code:
Answer 2:
观察上面的二叉树,可以发现,
当前层的集合 = 上一层的集合 + 上一层的集合加入当前层处理的元素, 即为当前的所有集合(树根为空集),因此可以从第二层开始(第一层空集)迭代的求出最后一层的所有集合(即叶子结点)
Attention:
1. 从第二层开始迭代,第一层视为空集,需要先初始化。
AC Code:
Answer 3 :
二进制思想(待研究 Bitmap)
可以根据二进制的思想,比如对于3个元素的集合,000表示一个元素都不选择,001表示选择第一个元素,101表示选择第一个和第三个元素...。因此如果集合大小为n,我们只需要让一个整数从0逐渐增加到2^n-1, 每个整数的二进制形式可以表示一个集合。如果用整数的二进制表示集合,这个算法有个限制,最大能表示集合元素的个数为64(unsigned
long long)。如果使用bitmap,然后模拟二进制的加1操作,则对集合大小就没有限制。刚好这一题集合的大小不超过64
AC Code:
LeetCode也有类似解法:
My Solution using bit manipulation
AC Code:
Given a set of distinct integers, S, return all possible subsets.
Note:
Elements in a subset must be in non-descending order.
The solution set must not contain duplicate subsets.
For example,
If S =
[1,2,3], a solution is:
[ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
Answer 1 :
DFS方法
思路解析:求集合的所有子集的问题。题目要求子集中元素非递减排列。因此,首先要对原来的集合排序。
原来的集合中的每一个元素在子集中只有两种状态:要么存在,要么不存在。这样构造子集的过程中每个元素就有两种选择方法,选择、不选择。因此可以构造一个二叉树,例如对例子中集合{1,2,3}构造的二叉树如下{左子树表示选择该层处理的元素,右子树表示不选择},最后得到的叶子结点就是要求的子集。
Attention:
1. 通过原来的集合的元素总数,判断是否到达叶子结点。
<strong> </strong>//达到叶子结点,一个集合元素选择结束 if(ileaf == S.size()) { ret.push_back(tmpres); return; }2. 每次对一个元素进行选择时,先push, 后pop. 下一层递归后返回到原函数此点,还是调用下一层递归前的状态(层层递归返回时依次pop掉了),所以pop的是该次push进的元素。
//选择ileaf元素 tmpres.push_back(S[ileaf]); subsets_helper(S, tmpres, ileaf + 1, ret); //不选择ileaf元素,将ileaf pop出来 tmpres.pop_back(); subsets_helper(S, tmpres, ileaf + 1, ret);
AC Code:
class Solution { public: vector<vector<int> > subsets(vector<int> &S) { vector<vector<int>> ret; vector<int> tmpres; int len = S.size(); if(len == 0) return ret; sort(S.begin(), S.end()); subsets_helper(S, tmpres, 0, ret); return ret; } void subsets_helper(vector<int>& S, vector<int>& tmpres, int ileaf, vector<vector<int>>& ret) { //达到叶子结点,一个集合元素选择结束 if(ileaf == S.size()) { ret.push_back(tmpres); return; } //选择ileaf元素 tmpres.push_back(S[ileaf]); subsets_helper(S, tmpres, ileaf + 1, ret); //不选择ileaf元素,将ileaf pop出来 tmpres.pop_back(); subsets_helper(S, tmpres, ileaf + 1, ret); } };
Answer 2:
观察上面的二叉树,可以发现,
当前层的集合 = 上一层的集合 + 上一层的集合加入当前层处理的元素, 即为当前的所有集合(树根为空集),因此可以从第二层开始(第一层空集)迭代的求出最后一层的所有集合(即叶子结点)
Attention:
1. 从第二层开始迭代,第一层视为空集,需要先初始化。
vector<vector<int> > res(1);//开始加入一个空集2. 由于每次添加的集合个数是由上一层决定的,下一层是上一层的两倍,所以需要处理每个元素前,计算上一层的集合个数,确定迭代次数。
int resSize = res.size(); for(int j = 0; j < resSize; j++)3. 注意先复制上一层的集合,再在该集合的最后一个元素后添加当前元素。注意末尾添加元素的方法
for(int j = 0; j < resSize; j++) { //复制一遍当前集合,并在其后添加元素S[i] res.push_back(res[j]); res.back().push_back(S[i]); }
AC Code:
class Solution { public: vector<vector<int> > subsets(vector<int> &S) { int len = S.size(); //第一层先加入一个空集合 vector<vector<int>> res(1); sort(S.begin(), S.end()); for(int i = 0; i < len; i++) { int resSize = res.size(); for(int j = 0; j < resSize; j++) { //复制一遍当前集合,并在其后添加元素S[i] res.push_back(res[j]); res.back().push_back(S[i]); } } return res; } };
Answer 3 :
二进制思想(待研究 Bitmap)
可以根据二进制的思想,比如对于3个元素的集合,000表示一个元素都不选择,001表示选择第一个元素,101表示选择第一个和第三个元素...。因此如果集合大小为n,我们只需要让一个整数从0逐渐增加到2^n-1, 每个整数的二进制形式可以表示一个集合。如果用整数的二进制表示集合,这个算法有个限制,最大能表示集合元素的个数为64(unsigned
long long)。如果使用bitmap,然后模拟二进制的加1操作,则对集合大小就没有限制。刚好这一题集合的大小不超过64
AC Code:
class Solution {
public:
vector<vector<int> > subsets(vector<int> &S) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
int len = S.size();
sort(S.begin(), S.end());
vector<vector<int> > res(1);//开始加入一个空集
unsigned long long bit = 1, bitmax = (1<<len);
vector<int> tmpres;
while(bit < bitmax)
{
tmpres.clear();
unsigned long long curBit = bit;
for(int i = 0; i < len; i++)//依次检测前len个二进制位
{
if(curBit & 1)
tmpres.push_back(S[i]);
curBit >>= 1;
}
res.push_back(tmpres);
bit++;
}
return res;
}
};
LeetCode也有类似解法:
My Solution using bit manipulation
AC Code:
class Solution { public: vector<vector<int> > subsets(vector<int> &S) { sort (S.begin(), S.end()); int elem_num = S.size(); int subset_num = pow (2, elem_num); vector<vector<int> > subset_set (subset_num, vector<int>()); for (int i = 0; i < elem_num; i++) for (int j = 0; j < subset_num; j++) if ((j >> i) & 1) subset_set[j].push_back (S[i]); return subset_set; } };
相关文章推荐
- leetcode 63 C++. Unique Paths II
- Leetcode_c++: Subsets (078)
- LeetCode 63 — Unique Paths II(C++ Java Python)
- leetcode subsets c++
- leetcode: Subsets
- Leetcode: Subsets
- [leetcode] subsets
- Leetcode: Subsets (Recursive)
- [LeetCode] Subsets
- LeetCode Online Judge 题目C# 练习 - Subsets
- [Leetcode 63] 77 Combinations
- Leetcode - Subsets
- [LEETCODE] Subsets
- leetcode Subsets II problem
- Leetcode中的回溯法题目总结:八皇后问题; unique path问题;subsets问题
- [Leetcode 64] 78 Subsets
- LeetCode: Subsets
- leetcode 47: subsets
- Leetcode: Subsets
- Leetcode中的回溯法题目总结:八皇后问题; unique path问题;subsets问题