四、遞迴(二)
阿新 • • 發佈:2020-12-26
1. 子集(leetcode 第78題)
# 在原子集的基礎上新增元素,擴充到result裡面 Slicing的方式 def subsets(nums): result = [[]] for num in nums: for element in result[:]: # slicing 相當於make copy ,這裡為什麼要make copy呢,直接result不行嗎?不行,隨著result不斷增加元素,會進入無限死迴圈 x = element[:] # 這裡為什麼會加slicing?因為不make copy的話,會修改掉原來的element,導致原子集消失x.append(num) result.append(x) return result
方法二:回溯演算法
def subsets_recursive(nums): lst = [] result = [] subsets_recursive_helper(result, lst, nums, 0) return result; def subsets_recursive_helper(result, lst, nums, pos): result.append(lst[:])# 新增路徑 子集問題需要在每個節點收集結果。 for i in range(pos, len(nums)): # 從選擇列表裡面挑選 lst.append(nums[i]) # 做選擇 subsets_recursive_helper(result, lst, nums, i+1) # 回溯 lst.pop() # 撤銷選擇
2. 子集Ⅱ(leetcode 第90題)
# 第一種解法 def subsets2(nums): res = [[]] for num in nums: res+= [ i + [num] for i in res if i + [num] not in res] return res # 第二種解法 def subsets_recursive2(nums): lst = [] result = [] nums.sort() # 先sort一下,以便於做比較 print(nums) subsets2_recursive_helper(result, lst, nums, 0); return result def subsets2_recursive_helper(result, lst, nums, pos): result.append(lst[:]) for i in range(pos, len(nums)): if (i > pos and nums[i] == nums[i-1]): # 就在這裡新增這一個限制條件即可 continue lst.append(nums[i]) subsets2_recursive_helper(result, lst, nums, i+1) lst.pop()
3. 排列(leetcode 面試題 08.07. 無重複字串的排列組合)
def perm(nums): res = [] perm_helper(res, nums) def perm_helper(res, nums): if (len(nums)==0): # 結束條件 這裡並不需要像前幾個題一樣每個節點都需要加進去,只需要新增葉子節點即可 print("".join(res)) for i in range(len(nums)): res.append(str(nums[i])) perm_helper(res, nums[0:i]+nums[i+1:]) # 將當前節點從選擇列表中刪除 res.pop()