一魚多吃 多角度切入 Subset 子集合生成 Leetcode #78

小松鼠
發佈於演算法專欄 個房間
閱讀時間約 3 分鐘

子集合生成是一道很經典的組合類上機考、面試題的題目。

今天,我們會試著用多個不同解度,並且複習以前學過的演算法框架來解這道題目。


原文的題目敘述


目標

給定n個相異的元素,產生所有的子集合。


測試範例

Example 1:

Input: nums = [1,2,3]
Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

Example 2:

Input: nums = [0]
Output: [[],[0]]

演算法1 直覺法 我手寫我口 + DFS

最直接的想法就是,單獨看每個元素,其實只有兩種選擇

一個是選進來當作子集合的成員,

另一個就是直接跳過不選。


因此,我們只要從第一個元素開始訪問,每層都展開 選擇/不選的兩個分支
一直到最後一個元素為止。

全部的元素都展開完之後,我們得到的所有可能情況就對應到所有的子集合。

示意圖1

raw-image


程式碼1 直覺法 我手寫我口 + DFS

class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:

all_subset = []
bag = []

# ----------------------------------------
def picker( i:int):

## Base case aka stop condition
# Terminate when all items are taken into consideration

if i == len(nums):
all_subset.append( bag[::] )
return


## General cases:

# Option_1: pick current item on index i
bag.append( nums[i] )
picker( i+1 )
bag.pop()

# Option_2: not to pick current item on index i
picker( i+1 )

return
# -----------------------------------------

# Let's start item picking from index 0
picker( 0 )
return all_subset

演算法2 回溯法+ DFS

前面的演算法框架教學已經提過,這種枚舉類的情境很適合使用回溯法
考慮每個選擇,做出每個選擇,同樣的模式遞迴展開下一層,撤回選擇

展開所有分支得到的答案就對應到每個子集合


教學影片2



示意圖2

raw-image


程式碼2 回溯法+ DFS

class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:


all_subset = []
bag = []


def makeSubsetFrom( startIndex ):

# Add current subset into final result
# Note: python object is passing by reference, so we have to make a copy
all_subset.append( bag[::] )


## Base cases aka stop condition:
# No more element
if startIndex == len(nums):
return

## General cases
# Current level, we choouse element on index i
for i in range(startIndex, len(nums) ):

bag.append( nums[i] ) # put this element into bag
makeSubsetFrom( i+1 ) # make subset from remaining elements
bag.pop() # undo selection

return

#----------------------------------------
makeSubsetFrom( startIndex = 0 )

return all_subset

演算法3 DP動態規劃

來自於一個基本觀察,每一層的子集合都是前一層的子集合衍伸而來的

情況a:前一層的子集合,照抄,保持不變,相當於當下這個新元素不選。

情況b:前一層的子集合在尾巴串上自己,相當於當下這個新元素選進來


教學影片3




示意圖3

raw-image


程式碼3 DP動態規劃 + Top-down 寫法

class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:

# Length = 0 <=> No element, which means empty set
dp = { 0: [ [] ] }

def makeFrom( i ):

# look-up DP table
if i in dp:
return dp[ i ]

# General cases:
# Current subsets
# = Previous subsets + (Previous subsets padding current element on the tail)
prev = makeFrom( i-1 )
cur = prev + [ prevSubset + [ nums[i-1] ] for prevSubset in prev]

dp[ i ] = cur
return cur

# ---------------------------------
return makeFrom( len(nums) )

程式碼3 DP動態規劃 + 等價Bottom-up 寫法

class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:

prev = [ [] ]
cur = [ [] ]

for number in nums:

cur = []

for subset in prev:
cur.append( subset )
cur.append( subset + [number] )

prev = cur

return cur

複雜度分析

時間複雜度: O(n * 2^n )

總共有2^n個子集合,每個子集合平均長度為O(n),
時間耗費在遞迴呼叫和複製子集合上。


空間複雜度: O(n * 2^n )

總共有2^n個子集合,每個子集合平均長度為O(n),
空間耗費在遞迴深度和複製子集合上。


關鍵知識點

萬變不離其宗,可以發現,總結歸納不管是DP還是DFS+回溯法都是同樣的思考核心。

每次有哪些選擇?

對於子集合來說,每個元素只有兩種可能,就是不選
依照題意進行模擬生成子集合即可。


Reference

[1] Leetcode_Subsets

52會員
339內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
一魚多吃 Linea + 銘文 + Particle Network一魚多吃 Linea + 銘文 + Particle Network,今天晚上按頭打 邀請: https://ally.build?inviteCode=AAE6J2 https://ally.build?inviteCode=QOCT15 https://ally.build?inviteC
Thumbnail
avatar
kevin111
2024-01-05
社群媒體世界「你掌握幾成?」 貼文總想一魚多吃…那經營失敗注定找上你這幾年在媒體社群上,著實下了不少功夫,說真的很多人都問說「臉書(Facebook)是不是真的要沒戲唱了?」其實我大多還是抱著比較樂觀的態度,如果你問身邊的年輕人,還用不用FB?那答案恐怕會讓你很心碎,一方面是自己的年紀已經不小,再者可能還會動搖你原本構思好的行銷計畫。 因此很多人在問我FB等等
Thumbnail
avatar
愛咪.C
2023-10-29
關於一主多奴-奴寵篇關於一主多奴,奴寵部份也該注意什麼? 要完全站在奴寵位置思考,還是有點難😅 1.妳能夠在理解之後,打心底接受這樣的關係嗎? 這邊說的接受,不是不停洗腦自己去接受這樣的關係,而是真的能夠接受這樣的關係,理解跟接受是兩回事。 2.妳曾想過想要怎樣的同伴嗎? 因為有時候,可能是妳和她相處的時間
avatar
可燃冰
2023-05-29
關於一主多奴-主人篇關於一主多奴,無論是主、奴哪方都需要注意的事項。 1.作為主人,你足夠坦誠嗎? 這邊指的坦誠,並不是指等你有了第一個奴一段時間,才突然坦承自己想要多收奴,而是一開始建立關係之前就必須告知讓奴方了解,這是義務,也是作為主人的責任。 在有第一位奴願意理解、接受之後,對後來遇到的第二位甚至往後幾位,
avatar
可燃冰
2023-05-29
一個人的成功不在於有多【聰明】而在於更能【熬】 很多的時候,大家都會認為一些成功者,都是很聰明的。【其實不然】。 阿里巴巴的創辦人馬雲,算是一位特別傳奇人物。 其中馬雲高中畢業,參加第一次高考(大學入學考試),大家應該不敢相信其中數學考了1分。
Thumbnail
avatar
Pedor Chang
2023-04-23
股票可以一魚多吃?股票可以一魚多吃? 可以,我們熟知的股票,主要是做價差或領股息,但是您知道,還可以做什麼用途嗎? 假如我們不要把股票賣掉,所以不做價差,那麼股票就可以做以下用途。
avatar
茉園生活隨筆
2022-12-20
【致親愛的你 系列】多留一點餘裕給自己和生活,這樣的人生才叫活過。說過上餘裕的生活,其實和「財富自由」沒有絕對關係⋯⋯時常覺得夢想和快樂是世上最快被放棄東西,無論是現實勒緊褲袋、或成就地位束縛,是說得頭頭是道卻毫無價值,總是第一個被捨棄⋯⋯
Thumbnail
avatar
陳然冉
2022-05-01
黃豆玉米多空懸於一線| 原物料觀察日記 美國農業部將於10/12公佈供需報告,從產量、期末庫存到單產,幾項重要指標皆普遍被預期會較前次調高。 產量:從4374百萬英斗上調至4415百萬英斗(區間4374- 4466百萬英斗) 期末庫存:從1850百萬英斗上調至3000百萬英斗(區間1610- 3730百萬英斗)
Thumbnail
avatar
諸葛呆的耕讀筆記- 外匯、經濟、黃小玉
2021-10-11
114號記錄:考思辨 你看得出論文原稿一魚多吃的問題嗎?童文薰律師在童溫層節目中整理出蔡英文一魚多吃的記錄 我其實蠻意外,在童文薰律師揭露蔡英文論文原稿一魚多吃之後,御用媒體會真的當回事發報導洗白的;因為這真的不是一般人會關心的事。但《芋傳媒》還真的引用了一個臉書粉專:《翻譯有要緊》的貼文煞有介事的這麼做了。
Thumbnail
avatar
台灣星火
2021-09-30
113號記錄:消失的一魚多吃期刊蔡英文的國圖版論文公佈之後,除了抄襲爭議外的另一個質疑,就是童文薰律師揭露的一魚多吃。而其中有趣的一則花絮就是...
Thumbnail
avatar
台灣星火
2021-09-30