題目:
給定一組不含重複元素的整數陣列 nums,返回該陣列所有可能的子集(冪集)。
說明:解集不能包含重複的子集。
示例:
輸入: nums = [1,2,3]分析:子集的大小可以是從0到nums.length,也就是可以為空集,也可以和原始集合一模一樣。此題還是採用回溯的方法進行求解,只不過,需要搞清楚,集合內部是不能有重複的元素存在的,每個子集所包含的元素(不考慮順序)也是不能相同的。輸出:[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
]
按照一般的解法時,可以以搜尋路徑長度作為遍歷的物件,搜尋路徑長度分別從0到nums.length,依次求出對應的搜尋結果集合,**實現如下:
private list>reslist;上面的**雖然解決了問題,但是由於需要挨個遍歷搜尋路徑的長度,所以效率十分低下,因此為了提高程式的效能,我對上面的**進行了優化。我們知道,這些子集的元素組合,數量較少的組合往往可以看作是元素數量較多的組合在相同搜尋路徑上的一部分,準確的說是前一部分。在整個搜尋結果中,搜尋路徑長度最長的情況就是路徑上包含了陣列中的所有元素,那麼我們回溯的意義是什麼呢?public list> subsets(int
nums)
reslist = new arraylist<>();
reslist.add(
new arraylist<>());
list
curlist = new arraylist<>();
for (int i = 1; i <= nums.length; i++)
return
reslist;
}private
void findsubsets(int nums, listcurlist, int s,int
curlen)
for (int j = s; j < nums.length; j++)
}
就是當到達某個點的時候,此時無法繼續向下了,那我們就返回上一層搜尋的點,然後基於返回的上一層的點,去尋找其他可走的路徑,也就是回溯尋找到的新路徑,之所以新,在於從某個點開始,路徑分開了,這個點之前的路徑節點都是相同的。
我們的做法是,從開始遍歷的點開始,每次前進一步,就記錄乙個搜尋結果,存入結果集合中。但是中間可能會產生重複的,比如如下圖所示,最左邊的路徑,如果3也遍歷完了,此時結果集中的集合是[1],[1,2],[1,2,3];然後開始向上回溯,根據回溯的特點,此時暫存元素的集合要刪除3,此時只剩下[1,2],而這時按照一貫的想法是在2這個點處,執行下一輪for迴圈,那麼遍歷訪問的還是3,那麼3就又走了一遍,所就產生了重複。那麼如何解決重複的問題呢?
前面說過,根據回溯和深度遍歷的規律,上面那種重複的原因在於,它們往往都是在前一部分是相同的路徑,然後在某個點處分開了,比如當在2這個點處,先走的是2+1這個,然後走完了回溯,此時2還在暫存元素列表,然後此時又走向了3,只不過不是基於2為父節點的搜尋,那麼就產生了重複。所以解決辦法就是採用乙個變數,去記錄某次遍歷下,上一次的訪問元素,比如訪問完3,回溯到了2,那麼上一次訪問的元素就是3,而此時再走向3的時候就會先和那個變數值就行比較,如果相等就直接跳過。
力扣 78 子集
給定一組不含重複元素的整數陣列 nums,返回該陣列所有可能的子集 冪集 說明 解集不能包含重複的子集。該題目來自力扣題庫 示例輸入 nums 1,2,3 輸出 1 2 1,2 3 1,3 2,3 1,2,3 思路使用位圖法 如果該陣列的長度是n,那麼該陣列的所有子集數目是2 n.使用兩層迴圈,外層...
力扣 78 子集
給定一組不含重複元素的整數陣列 nums,返回該陣列所有可能的子集 冪集 說明 解集不能包含重複的子集。示例 輸入 nums 1,2,3 輸出 3 1 2 1,2,3 1,3 2,3 1,2 利用位數為陣列長度的二進位制數,這個二進位制數所能表示的元素個數剛好等於這個冪集的子集的個數,且二進位制數的...
78 子集 力扣(LeetCode)
給定一組不含重複元素的整數陣列 nums,返回該陣列所有可能的子集 冪集 說明 解集不能包含重複的子集。示例 輸入 nums 1,2,3 輸出 3 1 2 1,2,3 1,3 2,3 1,2 求乙個陣列元素的所有組合 求乙個集合的冪集 回溯法 求乙個集合的冪集 用遞迴求解 class solutio...