DFS 算法模板

dfs算法模板:html

一、下一層是多節點的dfs遍歷node

def dfs(array or root, cur_layer, path, result):
    if cur_layer == len(array) or not root:
        result.append(path)
        return
    
    for i in range(cur_layer, len(array)):
        do something with array[cur_layer:i+1] or nodes with this layer
        path.append(xxx) # 修改path 或者 其餘操做
        dfs(array, i + 1 or cur_layer + 1, path, result)
        path.pop() # 還原path 或者 還原以前的操做

 

不含重複元素的全排列模板,交換思路:python

class Solution:
    """
    @param: :  A list of integers
    @return: A list of unique permutations
    """
 
    def permute(self, nums):
        # write your code here
        result = []
        self.find_permutations(nums, 0, result)
        return result
 
 
    def find_permutations(self, nums, start_index, result):
        if start_index >= len(nums):
            result.append(list(nums))
            return
 
        for i in range(start_index, len(nums)):
            nums[start_index], nums[i] = nums[i], nums[start_index]
            self.find_permutations(nums, start_index + 1, result)
            nums[start_index], nums[i] = nums[i], nums[start_index]

 含重複元素的全排列,交換思路,和上述代碼比較無非是多了一個if判斷:正則表達式

class Solution:
    """
    @param: :  A list of integers
    @return: A list of unique permutations
    """
 
    def permuteUnique(self, nums):
        # write your code here
        result = []
        self.find_permutations(nums, 0, result)
        return result
 
    def find_permutations(self, nums, start_index, result):
        if start_index >= len(nums):
            result.append(list(nums))
            return
 
        for i in range(start_index, len(nums)):
            if nums[i] in nums[start_index:i]:
                continue
             
            nums[start_index], nums[i] = nums[i], nums[start_index]
            self.find_permutations(nums, start_index + 1, result)
            nums[start_index], nums[i] = nums[i], nums[start_index]

 

不含重複元素的組合算法,無腦式的先排序:算法

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

 含重複元素的組合算法,無腦式的先排序,加一個if去重:app

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

案例參考:ide

https://www.cnblogs.com/bonelee/p/11668685.htmlpost

https://www.cnblogs.com/bonelee/p/11667428.html測試

 

二、下一層僅2個節點的dfs,也就是二叉樹的dfsthis

先序遍歷,迭代和遞歸寫法都要熟悉:

def preoder_traversal(root):
    if not root:
        return 
    
    stack = [root]
    while stack:
        node = stack.pop()
        do something with node
        if node.right:
            stack.append(node.right)
        if node.left:
            stack.append(node.left)
    return xxx


def preoder_traversal(root):
    if not root:
        return 
    
    do something with root
    preoder_traversal(root.left)
    preoder_traversal(root.right)

 中序遍歷,迭代和遞歸寫法:

def inoder_traversal(root):
    if not root:
        return

    stack = []
    node = root
    while stack or node:
        if node:
            stack.append(node)
            node = node.left
        else:
            cur_node = stack.pop()
            do something with cur_node
            node = cur_node.right
    return xxx


def inoder_traversal(root):
    if not root:
        return

    inoder_traversal(root.left)
    do something with root
    inoder_traversal(root.right)

 後序遍歷,僅僅掌握遞歸寫法:

def post_order_traversal(root):
    if not root:
        return

    post_order_traversal(root.left)
    post_oder_traversal(root.right)
    do something with root

遍歷過程當中須要記住上次遍歷節點才能獲得結果的,模板(中序和後序僅僅換下if else代碼位置):

last_node = None
def dfs(root):
   if last_node is None:
	last_node = root
   else:
        compare(last_node, root)....
	last_node = root
   dfs(root.left)
   dfs(root.right)

 

3. BST的搜索,比較簡單直觀,和二分相似:

def bst_search(root, target):
                if not root:
                    return None

                node = root
                while node:
                    if node.val < target:
                        node = node.right
                    elif node.val > target:
                        node = node.left
                    else:
                        return node.val
                return xxx

 

---------------------------

DFS總結:
一、第一次講的dfs模板必定要記住。
二、二叉樹的遍歷,https://www.cnblogs.com/rnanprince/p/11595380.html,先序中序的遞歸和迭代寫法必須掌握,像算法模板同樣記住。後序遍歷只掌握遞歸寫法。
三、遍歷過程當中須要記住上次遍歷節點才能獲得結果的,記住模板。
last_node = None
def dfs  (root):
   if last_node is None:
	last_node = root
   else:
     compare(last_node, root)....
	 last_node = root
   dfs(root.left)
   dfs(root.right)
四、BST的搜索代碼要會,要記住。
五、排列組合類題目:
組合類算法,都使用分治+遞歸的思路去寫,重複元素,先排序,無非多了一個判斷。
排列類算法,用交換思路,都使用分治+遞歸的思路去寫,重複元素,無非多了一個判斷。
六、隱式圖搜索:八皇后,正則表達式匹配,word拼圖

i        j
|        | 
abc  ==> abc   dfs(i+1, j+1)
a*bc ==> aaabc dfs(i+2, j) or dfs(i, j+1)
a.bc ==> adbc  dfs(i+1, j+1) 


  a b c
  g a n
  a x x
  i x x
  n x x
dfs(左邊走)
dfs(右邊走)
dfs(上邊走)
dfs(下邊走)
走的過程當中將路徑記下來

七、常見問題:
  超時的處理:剪枝(cache、trie去剪枝),修改算法bfs,用dp
  測試用例過不完:本身debug,放到ide去調試
相關文章
相關標籤/搜索