【LeetCode】236. 二叉树的最近公共祖先

这篇博客讨论了如何在LeetCode中解决寻找二叉树中两个节点的最近公共祖先问题。作者首先展示了一种使用倍增算法的解决方案,虽然能正确找到LCA,但由于节点大小未知,无法直接用值作数组下标。然后,作者介绍了官方的递归解法,该方法更为经典。博客通过具体的代码示例解释了两种方法的实现细节,并给出了测试用例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.题目

题目链接

2.代码一

下面这段代码使用的是倍增思想,虽然可以得到正确的返回值,但是LeetCode中给出的如下两个限制让这题使用倍增算法不是那么顺利:

  • 需要知道是哪个节点的值,即最后需要返回这个节点,而不是这个节点的值
  • 给出的数据的节点大小是未知的,所以不能简单的使用val值作为数组的下标存储
from queue import Queue
import math
# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
         self.val = x
         self.left = None
         self.right = None

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        height = [0] * 10
        ancestor = [[0 for i in range(5)] for j in range(10)]
        self.bfs(root,height,ancestor)

        # print(height) 
        p_val = p.val
        q_val = q.val
        # print(p_val)
        # print(q_val)
        while(height[p_val] < height[q_val]):
            q_val = ancestor[q_val][0] # 往上找一次

        while(height[p_val] > height[q_val]):
            p_val = ancestor[p_val][0] 
        # print(q_val)
        # print(p_val)
        if q_val == p_val:
            return q_val
        # 现在二者的高度相同,可以使用倍增算法寻找了        
        k = int(math.log2(height[q_val]))        
        for i in reversed(range(0,k+1)):
            if(ancestor[q_val][i] == ancestor[p_val][i] ):
                continue
            else:
                q_val = ancestor[q_val][i]
                p_val = ancestor[p_val][i]
        
        # 需要返回这个节点对应的node,而不是值
        
        return ancestor[q_val][0]
        
        
    # 使用广度优先得到每个节点的高度信息,根节点为0
    # 同时给 ancestor[i][j] 赋值,得到每个节点的祖先节点信息
    def bfs(self,root,height,ancestor):
        que = Queue()
        que.put((root,0))
        # print("----")
        # print("root.val",root.val)
        height[root.val] = 0
        while(que.qsize()):
            head,dis = que.get()
            k = int(math.log2(dis+1))
            
            if head.left is not None:
                # print(head.left.val)
                left_val = head.left.val
                
                que.put((head.left,dis+1))
                height[head.left.val] = dis+1
                ancestor[head.left.val][0] = head.val                                 
                # 开始对各级祖先赋值
                for i in range(1,k+1): 
                    ancestor[left_val][i] = ancestor[ancestor[left_val][i-1]][i-1]

            if head.right is not None:
                right_val = head.right.val
                # print(right_val)
                que.put((head.right,dis+1))
                height[right_val] = dis+1
                ancestor[right_val][0] = head.val

                for i in range(1,k+1): 
                    ancestor[right_val][i] = ancestor[ancestor[right_val][i-1]][i-1]

node10 = TreeNode(10,None,None)
node9 = TreeNode(9,node10,None)
node8 = TreeNode(8,node9,None)
node7 = TreeNode(7,None,None)
node4 = TreeNode(4,None,None)
node0 = TreeNode(0,None,None)
node8 = TreeNode(8,None,None)
node6 = TreeNode(6,None,None)
node2 = TreeNode(2,node7,node4)
node5 = TreeNode(5,node6,node2)
node1 = TreeNode(1,node0,node8)
node3 = TreeNode(3,node5,node1)

s = Solution()
out = s.lowestCommonAncestor(node3,node5,node1)
print(out)

3.代码二

使用递归的思想,LeetCode官方给出的解答还是挺经典的。我这个科班生菜到之前竟然没有在意这么写过这道题。惭愧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

说文科技

看书人不妨赏个酒钱?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值