[Go版]算法通关村第八关黄金——寻找祖先问题(二叉树最难问题之一)

目录

  • 题目:二叉树的最近公共祖先
    • 解法一:从根节点从上到下递归遍历找
      • 思路分析
      • 复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( n ) O(n) O(n)
      • Go代码
    • 解法二:从p、q节点向根节点方向遍历找第一个公共父节点
      • 思路分析
      • 复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( n ) O(n) O(n)
      • Go代码

题目:二叉树的最近公共祖先

题目链接:LeetCode-236. 二叉树的最近公共祖先
[Go版]算法通关村第八关黄金——寻找祖先问题(二叉树最难问题之一)_第1张图片

解法一:从根节点从上到下递归遍历找

思路分析

[Go版]算法通关村第八关黄金——寻找祖先问题(二叉树最难问题之一)_第2张图片

  1. 如果p或者q就是root节点,则第一个公共父节点就是root,因为根据定义最近公共父节点可以是节点本身。(比如上图:p=3 q=8 或者 q=3 p=2)
  2. 如果递归到叶子节点了,但是还没有找到p或q,则直接返回nil,上层会再回溯判断的。
  3. 从根节点root往左右子树看,
    1. 如果p q在同一侧,则可以直接放弃另一侧的递归查找,直接从同侧递归下去即可。(比如上图:p=5 q=7 或者 p=0 q=8)
    2. 如果p q分布在两侧,则继续左右递归下去。(比如上图:p=5 q=0 或者 p=7 q=1)

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( n ) O(n) O(n)

Go代码

 func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
     if root == nil || root == p || root == q {
         return root
     }
     if root.Left == nil && root.Right == nil {
         return nil
     }
     left := lowestCommonAncestor(root.Left, p, q)
     right := lowestCommonAncestor(root.Right, p, q)
     if left != nil && right != nil {
         return root
     }
     if left == nil {
         return right
     }
     return left
}

解法二:从p、q节点向根节点方向遍历找第一个公共父节点

思路分析

  1. 先遍历所有子节点,将其的父节点找到,放入map中存储,方便之后直接从任一节点定位其父节点。
  2. 从p节点开始找他的所有父节点,并放入到p的父节点map中存储。
  3. 从q节点开始判断他的父节点是否在p的父节点map中存在,不存在就继续下一个父节点找,这样找到的第一个存在于p父节点map中的节点就是p和q的公共父节点。
  4. 如果最后都没有找到,说明p或者q不在该树中。

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( n ) O(n) O(n)

Go代码

 func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root == nil || root == p || root == q {
        return root
    }
    parentMap := make(map[int]*TreeNode, 0)
    pParentMap := make(map[*TreeNode]bool, 0)
    // 把所有节点对应的父节点都找到
    var findParent func(*TreeNode)
    findParent = func(node *TreeNode) {
        if node.Left != nil {
            parentMap[node.Left.Val] = node
            findParent(node.Left)
        }
        if node.Right != nil {
            parentMap[node.Right.Val] = node
            findParent(node.Right)
        }
    }
    findParent(root)
    // 找到p的所有父节点
    for p != nil {
        pParentMap[p] = true
        p = parentMap[p.Val]
    }
    // 找到p和q的第一个公共父节点
    for q != nil {
        if pParentMap[q] {
            return q
        }
        q = parentMap[q.Val]
    }
    return nil
}

你可能感兴趣的:(算法与数据结构,golang,算法)