# **Leetcode筆記(Subsets)** :::info :information_source: 題目 : Subsets, 類型 : recursion , 等級 : medium 日期 : 2023/05/29,2023/07/10,2023/12/10,2024/10/10 ::: ### 嘗試 2023/07/10 永遠有兩個選擇,要添加當前數字與不添加當前數字,選擇完後,把全部的結果放到下一層,並且進來新的數字同樣做兩種選擇 1. 需要先初始化[] 2. 每次添加一個nums列表的數字 3. 在subSet中,需要用index去跌代,因為subSet會不停增長(會memory limit exceed) 4. 需要用copy()去創造兩個獨立的變數,否則會互相連動 ```python class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: subSet = [[]] for n in nums: for i in range(len(subSet)): subNew = subSet[i].copy() subNew.append(n) # 新增 subSet.append(subNew) return subSet ``` 2023/12/10 ```python class Solution(object): def subsets(self, nums): res = [] def backtracking(i, path): if i == len(nums): res.append(list(path)) return backtracking(i + 1, path + [nums[i]]) backtracking(i + 1, path) backtracking(0, []) return res ``` 2024/10/10 ```python class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: res = [] self.traverse(nums, res, [], 0) return res def traverse(self, nums, res, path, start): res.append(path) for i in range(start, len(nums)): self.traverse(nums, res, path + [nums[i]], i + 1) ``` --- ### **優化** 在 Python 中,列表是可变对象,所以直接对列表进行操作可能会导致原列表的修改,所以通過使用copy,會另外複製出一串新的列表,不會對原列表產生影響 --- 時間複雜度: - 外層循環遍歷 `nums` 列表,所以它的時間複雜度為 O(len(nums))。 - 內層循環遍歷 `subset` 列表,其長度會逐步增加,但每個元素最多只會被訪問一次。所以,內層循環的總時間複雜度可以近似看作 O(2^len(nums)),因為對於每個元素,我們都需要複製一份並添加到 `subset` 中。 因此,總體時間複雜度為 O(len(nums) * 2^len(nums))。 空間複雜度: - 初始時,我們創建了一個空列表 `subset`,佔用 O(1) 的空間。 - 隨著循環的進行,我們不斷向 `subset` 中添加新的子集,最終的 `subset` 列表的長度將達到 2^len(nums)。 - 每個子集的平均長度為 len(nums)/2,因為每個元素可能在子集中出現或不出現。 - 所以,子集的總空間佔用為 O(2^len(nums) * len(nums)/2) = O(2^len(nums) * len(nums))。 因此,總體空間複雜度為 O(2^len(nums) * len(nums))。 ```python class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: subset = [[]] # len([[]])為1 for n in nums: for i in range(len(subset)): # 不可以用for sub in subset # sub_copy = sub.copy()因為處理完一個subset # for 迴圈的subset就會更新,就會無限循環 # 達到Memory Limit Exceeded # 先處理上一層的各個元素 + 這一層的n sub_copy = subset[i].copy() sub_copy += [n] # 把上一層的答案與這一層"新的"添加再一起 subset.append(sub_copy) return subset ``` --- **:warning: 錯誤語法** :::warning ::: **:thumbsup:學習** :::success ::: **思路** 最一開始先初始化[[]],然後依序遍歷nums裡面的東西,把 ( 原始subset沿用 + 原始.append新加的數字 ) , 例如第一層就是沿用[],再加上[1], 第二層就是沿用[],[1],再加上2,即[2],[1,2] 第三層就是沿用以上四個,再加上3 ![](https://hackmd.io/_uploads/rJ93QAW8h.png) **講解連結** https://www.youtube.com/watch?v=6mlWs0iABjs&ab_channel=%E4%BB%8A%E5%A4%A9%E6%AF%94%E6%98%A8%E5%A4%A9%E5%8E%B2%E5%AE%B3 Provided by. 今天比昨天厲害 ###### tags: `recursion` `medium` `leetcode`