17. 子集
給定一個含不一樣整數的集合,返回其全部的子集。python
樣例
樣例 1:markdown
輸入:[0] 輸出: [ [], [0] ]
樣例 2:app
輸入:[1,2,3] 輸出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
挑戰
你能夠同時用遞歸與非遞歸的方式解決麼?spa
注意事項
子集中的元素排列必須是非降序的,解集必須不包含重複的子集。code
時間複雜度是O(2^n),本質就是在作二叉樹的dfs。[1,2,3]舉例:blog
root遞歸
/ \ip
不選中1 選中1get
/ \ / \it
不選中2 選中2 不選中2 選中2
。。。。。
使用dfs記錄遍歷路徑便可。
class Solution: """ @param nums: A set of numbers @return: A list of lists """ def subsets(self, nums): # write your code here path, results = [],[] self.helper(sorted(nums), 0, path, results) return results def helper(self, nums, index, path, results): if index == len(nums): results.append(list(path)) return path.append(nums[index]) self.helper(nums, index+1, path, results) path.pop() self.helper(nums, index+1, path, results)
第二種寫法是使用位運算,也比較直觀,代碼很容易寫出來:
class Solution: """ @param nums: A set of numbers @return: A list of lists """ def subsets(self, nums): # write your code here nums = sorted(nums) n = len(nums) results = [] for i in range(1<<n): results.append(self.get_num(nums, i, n)) return results def get_num(self, nums, num, cnt): result = [] for i in range(cnt): if num & (1<<i): result.append(nums[i]) return result
第三種寫法是使用for dfs寫法,看下面的圖,以【1,2,3】爲例:
root (path=[])
|
----------------------------------------
| | |
1 2 3
/ \ |
2 3 3
/
3
在遍歷上述樹的過程當中將path所有記錄下來(path不用走到葉子節點):
class Solution: """ @param nums: A set of numbers @return: A list of lists """ def subsets(self, nums): # write your code here nums = sorted(nums) path, result = [], [] self.dfs(nums, 0, path, result) return result def dfs(self, nums, index, path, result): result.append(list(path)) if index == len(nums): return for i in range(index, len(nums)): path.append(nums[i]) self.dfs(nums, i+1, path, result) path.pop()
含有重複元素的子集問題,例如【1,2,2,3】
root (path=[])
|
----------------------------------------
| | | |
1 2 2(重複) 3
/ \ / \ |
2 3 2 3 3
/ \ |
2 3 3
|
3
又例如【1,1,2,3】
root (path=[])
|
----------------|-------------------------
| 1(重複) | |
1 / \ 2 3
/ | \ 2 3 |
1 2 3 | 3
/ \ | 3
2 3 3
|
3
因此代碼以下:
class Solution: """ @param nums: A set of numbers. @return: A list of lists. All valid subsets. """ def subsetsWithDup(self, nums): # write your code here nums = sorted(nums) path, result = [], [] self.dfs(nums, 0, path, result) return result def dfs(self, nums, index, path, result): result.append(list(path)) for i in range(index, len(nums)): if i > 0 and nums[i] == nums[i-1] and i > index: continue path.append(nums[i]) self.dfs(nums, i+1, path, result) path.pop()