zoukankan      html  css  js  c++  java
  • DFS 算法模板

    dfs算法模板:

    1、下一层是多节点的dfs遍历

    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 或者 还原之前的操作
    

    不含重复元素的全排列模板,交换思路:

    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去重:

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

    案例参考:

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

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

    2、下一层仅2个节点的dfs,也就是二叉树的dfs

    先序遍历,迭代和递归写法都要熟悉:

    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总结:
    1、第一次讲的dfs模板一定要记住。
    2、二叉树的遍历,https://www.cnblogs.com/rnanprince/p/11595380.html,先序中序的递归和迭代写法必须掌握,像算法模板一样记住。后序遍历只掌握递归写法。
    3、遍历过程中需要记住上次遍历节点才能得到结果的,记住模板。
    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)
    4、BST的搜索代码要会,要记住。
    5、排列组合类题目:
    组合类算法,都使用分治+递归的思路去写,重复元素,先排序,无非多了一个判断。
    排列类算法,用交换思路,都使用分治+递归的思路去写,重复元素,无非多了一个判断。
    6、隐式图搜索:八皇后,正则表达式匹配,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(下边走)
    走的过程中将路径记下来
    
    7、常见问题:
      超时的处理:剪枝(cache、trie去剪枝),修改算法bfs,用dp
      测试用例过不完:自己debug,放到ide去调试
    
  • 相关阅读:
    八十九:ECMAScript6扩展之字符串、for-of
    八十八:ECMAScript6之解构赋值
    八十七:ECMAScript6基础入门之let、const
    八十六:JavaScript之表单验证案例
    八十五:JavaScript之正则表达式之实现正则测试工具
    八十四:JavaScript之正则表达式之常用的正则表达式
    vim常用命令总结(转)
    Linux常用命令
    LinkedBlockingQueue的put,add跟offer的区别
    RabbitMQ消息确认(发送确认,接收确认)
  • 原文地址:https://www.cnblogs.com/bonelee/p/11741985.html
Copyright © 2011-2022 走看看