求子集

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;

? ? }

};

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,872評論 0 10
  • 獨木舟說,不管以后我會遇到誰,會經歷什么,我都不相信愛情了。 張嘉佳說,不管我曾經經歷了什么,我依然相信愛情。 我...
    羥羊閱讀 466評論 0 2
  • 現(xiàn)在進入冥想非常的快,感覺把意識集中在眉心時,整個人就寧靜下來,隨著身體的每一個部分的放松,頭腦的疲倦和壓力都慢慢...
    趙小花_喜悅閱讀 924評論 0 0
  • 我想你一定還記得小明同學。 見到李曉明是在酒店門口,他坐在車里等著我們。 李曉明是我的小學同學,...
    安寧笑看人生閱讀 544評論 0 0
  • 雖然小朋友大部分時間都是軟糯甜萌,但也有非常annoying的時候。 最近感覺她已經提前進入terrible 2了...
    有魚閱讀 347評論 0 1

友情鏈接更多精彩內容