http://www.cnblogs.com/grandyang/p/4309345.html
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,
IfS=[1,2,3], a solution is:
[
? [3],
? [1],
? [2],
? [1,2,3],
? [1,3],
? [2,3],
? [1,2],
? []
]
這道求子集合的問題,由于其要列出所有結果,按照以往的經驗,肯定要是要用遞歸來做。這道題其實它的非遞歸解法相對來說更簡單一點,下面我們先來看非遞歸的解法,由于題目要求子集合中數(shù)字的順序是非降序排列的,所有我們需要預處理,先給輸入數(shù)組排序,然后再進一步處理,最開始我在想的時候,是想按照子集的長度由少到多全部寫出來,比如子集長度為0的就是空集,空集是任何集合的子集,滿足條件,直接加入。下面長度為1的子集,直接一個循環(huán)加入所有數(shù)字,子集長度為2的話可以用兩個循環(huán),但是這種想法到后面就行不通了,因為循環(huán)的個數(shù)不能無限的增長,所以我們必須換一種思路。我們可以一位一位的網(wǎng)上疊加,比如對于題目中給的例子[1,2,3]來說,最開始是空集,那么我們現(xiàn)在要處理1,就在空集上加1,為[1],現(xiàn)在我們有兩個自己[]和[1],下面我們來處理2,我們在之前的子集基礎上,每個都加個2,可以分別得到[2],[1, 2],那么現(xiàn)在所有的子集合為[], [1], [2], [1, 2],同理處理3的情況可得[3], [1, 3], [2, 3], [1, 2, 3], 再加上之前的子集就是所有的子集合了,代碼如下:
解法一:

// Non-recursionclass Solution {public:
? ? vector > subsets(vector &S) {
? ? ? ? vector > res(1);
? ? ? ? sort(S.begin(), S.end());
? ? ? ? for(inti =0; i < S.size(); ++i) {
? ? ? ? ? ? intsize = res.size();
? ? ? ? ? ? for(intj =0; j < size; ++j) {
? ? ? ? ? ? ? ? res.push_back(res[j]);
? ? ? ? ? ? ? ? res.back().push_back(S[i]);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return res;
? ? }
};

整個添加的順序為:
[]
[1]
[2]
[1 2]
[3]
[1 3]
[2 3]
[1 2 3]
下面來看遞歸的解法,相當于一種深度優(yōu)先搜索,參見網(wǎng)友JustDoIt的博客,由于原集合每一個數(shù)字只有兩種狀態(tài),要么存在,要么不存在,那么在構造子集時就有選擇和不選擇兩種情況,所以可以構造一棵二叉樹,左子樹表示選擇該層處理的節(jié)點,右子樹表示不選擇,最終的葉節(jié)點就是所有子集合,樹的結構如下:

? ? ? ? ? ? ? ? ? ? ? ? []? ? ? ?
? ? ? ? ? ? ? ? ? /? ? ? ? ? \? ? ? ?
? ? ? ? ? ? ? ? ? /? ? ? ? ? ? \? ?
? ? ? ? ? ? ? ? /? ? ? ? ? ? ? \
? ? ? ? ? ? ? [1]? ? ? ? ? ? ? ? []
? ? ? ? ? /? ? ? \? ? ? ? ? /? ? \
? ? ? ? ? /? ? ? ? \? ? ? ? /? ? ? \? ? ? ?
? ? ? [12]? ? ? [1]? ? ? [2]? ? []
? ? ? /? ? \? ? /? \? ? /? \? ? / \
? [123] [12] [13] [1] [23] [2] [3] []

解法二:

// Recursionclass Solution {public:
? ? vector > subsets(vector &S) {
? ? ? ? vector > res;
? ? ? ? vectorout;
? ? ? ? sort(S.begin(), S.end());
? ? ? ? getSubsets(S, 0,out, res);
? ? ? ? return res;
? ? }
? ? voidgetSubsets(vector &S,intpos, vector &out, vector > &res) {
? ? ? ? res.push_back(out);
? ? ? ? for(inti = pos; i < S.size(); ++i) {
? ? ? ? ? ? out.push_back(S[i]);
? ? ? ? ? ? getSubsets(S, i +1,out, res);
? ? ? ? ? ? out.pop_back();
? ? ? ? }
? ? }
};

整個添加的順序為:
[]
[1]
[1 2]
[1 2 3]
[1 3]
[2]
[2 3]
[3]
最后我們再來看一種解法,這種解法是CareerCup書上給的一種解法,想法也比較巧妙,把數(shù)組中所有的數(shù)分配一個狀態(tài),true表示這個數(shù)在子集中出現(xiàn),false表示在子集中不出現(xiàn),那么對于一個長度為n的數(shù)組,每個數(shù)字都有出現(xiàn)與不出現(xiàn)兩種情況,所以共有2n中情況,那么我們把每種情況都轉換出來就是子集了,我們還是用題目中的例子, [1 2 3]這個數(shù)組共有8個子集,每個子集的序號的二進制表示,把是1的位對應原數(shù)組中的數(shù)字取出來就是一個子集,八種情況都取出來就是所有的子集了,參見代碼如下:
?123Subset
0FFF[]
1FFT3
2FTF2
3FTT23
4TFF1
5TFT13
6TTF12
7TTT123
解法三:

class Solution {public:
? ? vector > subsets(vector &S) {
? ? ? ? vector > res;
? ? ? ? sort(S.begin(), S.end());
? ? ? ? intmax =1<< S.size();
? ? ? ? for(intk =0; k < max; ++k) {
? ? ? ? ? ? vectorout= convertIntToSet(S, k);
? ? ? ? ? ? res.push_back(out);
? ? ? ? }
? ? ? ? return res;
? ? }
? ? vector convertIntToSet(vector &S,int k) {
? ? ? ? vector sub;
? ? ? ? intidx =0;
? ? ? ? for(inti = k; i >0; i >>=1) {
? ? ? ? ? ? if((i &1) ==1) {
? ? ? ? ? ? ? ? sub.push_back(S[idx]);
? ? ? ? ? ? }
? ? ? ? ? ? ++idx;
? ? ? ? }
? ? ? ? return sub;
? ? }
};
