1. 程式人生 > 實用技巧 >四、遞迴(二)

四、遞迴(二)

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()