【LeetCode & 劍指offer刷題】回溯法與暴力列舉法題7:Subsets(系列)
阿新 • • 發佈:2019-01-06
【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...)
Subsets
Given a set of distinct integers, nums , return all possible subsets (the power set). Note: The solution set must not contain duplicate subsets.C++ //子集問題1:返回一個數組所有子集(不包含重複元素) /* 方法一:遞迴 每個元素,都有兩種選擇,選或不選 增量構造法,深搜,時間複雜度O(2^n),空間複雜度O(n) 需包含空集
//子集問題2: 返回一個數組所有子集(可能包含重複元素) /* 遞迴法: 與 subsets I 不同之處在與,每次 dfs 就 push 結果,即每個分支就 push 該路徑,而不是到末尾之後 push 例子: 輸入 [1,2,2], 遞迴樹為 - 1 - 2 -2 [] - 2 - 2 故結果為 [] 1 12 122 2 22 通過限制使每個父結點的子結點元素不相同,從而構造子集 */ /* 方法二:也可以統計每個元素出現的次數,用類似排列2的做法,不過還沒想明白
*/ class Solution { public : vector < vector < int >> subsetsWithDup ( vector < int >& nums ) { vector < vector < int >> result ; vector < int > path ; if ( nums . empty ()) return result ; sort ( nums . begin (), nums . end ()); //必須排序,這樣重複的數才會相鄰 dfs ( nums , 0 , path , result ); return result ; } private : //start 為每個父結點的子結點開始的數,子結點取 nums[start~end], 但不能取重複數 void dfs ( vector < int >& nums , int start , vector < int >& path , vector < vector < int >>& result ) { result . push_back ( path ); //每個結點都push,包括根結點(對應空vector) for ( int i = start ; i < nums . size (); i ++) // 產生某個父結點的多個子結點 ( 子結點值不能相同 ), 但父結點可以與子結點相同, if 語句中的 i!=start 所起作用 { if ( i != start && nums [ i ] == nums [ i - 1 ]) continue ; // 如果同一個父結點的當前子結點值與上一個子結點相同,則不執行下面遞迴程式碼,進行分支開闢 path . push_back ( nums [ i ]); dfs ( nums , i + 1 , path , result ); // 注意這裡傳遞 i+1,類似組合問題的遞迴法 path . pop_back (); // 給下個分支騰出空間 } } };