代码随想录 Day 18 | 【第六章 二叉树 part06】530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

一、530.二叉搜索树的最小绝对差

需要领悟一下二叉树遍历上双指针操作,优先掌握递归

1. 直白想法

        采用中序遍历,将这棵树转变为一个递增的有序数组,再对数组进行遍历。计算相邻两个数之间的差值,返回最小的绝对差。

2. 双指针法

        在直白想法的基础上优化,通过定义一个指针指向前一个节点,另一个指针指向当前节点,用两个指针相减直接得到绝对差,就不需要将树转化为数组再进行遍历了。

(1)定义一个变量result记录相邻节点的最小绝对差,将其初始化为一个最大值。定义一个指针pre,将其初始化为None。

(2)定义函数的参数和返回值。因为本题定义了全局变量result和pre,所以递归函数不需要返回值。传入cur,作为当前遍历的节点。

(3)确定终止条件。遍历到当前节点为空,不需要返回值,所以只写一个return。

(4)单层递归遍历。本题采用中序遍历,先向左遍历;再处理中间节点,如果pre节点不为空,那么就可以记录cur和pre节点的差值,更新result采用min函数,取差值和原始result中间的最小值,最后为了使cur和pre始终紧密相连,所以更新pre指向cur;接下来可以向右递归。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.result = float('inf')
        self.pre = None
    def traversal(self, cur):
        if cur is None:
            return 

        # left:
        self.traversal(cur.left)

        # middle:
        if self.pre is not None:
            self.result = min(self.result, cur.val-self.pre.val)
        self.pre = cur

        # right:
        self.traversal(cur.right)
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        self.traversal(root)
        return self.result
        

二、501.二叉搜索树中的众数

和 530差不多双指针思路,不过 这里涉及到一个很巧妙的代码技巧。

1. 双指针法

(1)定义pre指针,找到当前遍历节点的前一个节点;定义count,记录元素出现的频率;定义max_count,记录当前遍历节点中出现频率最高的;定义结果集数组result,用于存放结果集。

(2)定义递归函数,传入的是二叉树根节点,返回值为void,因为遍历整个二叉树,并且在遍历过程中直接对元素进行统计,结果也存放在result里了,因此不需要返回值。

(3)终止条件为cur遇到空,直接返回即可。

(4)中序遍历:

        左:直接递归遍历;

        中:1)if:如果pre指针为null,即递归遍历的第一个元素,因此count等于1,也就是该元素目前出现的频率为1;elif:如果pre指针指向的元素等于cur指针指向的元素,那么count+=1,也就是这个元素出现的频率加1。else:说明pre和cur不相等,所以count变回1;

                2)递归:pre=cur;

                3)收获结果:如果count等于max_count,那么将其放进结果集;如果count大于max_count,那么将max_count更新为count,由于max_count更新,那么说明之前结果集的元素不是我们真正想要的结果,所以清空result结果集,再将当前结果放进结果集。这样完成了result的实时更新。

        右:向右遍历,最后返回。

2. 代码实现

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.result = []
        self.pre = None
        self.count = 0
        self.max_count = 0

    def traversal(self, cur):
        if cur is None:
            return

        # left:
        self.traversal(cur.left)

        # middle:
        if self.pre is None:
            self.count = 1
        elif cur.val == self.pre.val:
            self.count += 1
        else: self.count = 1

        self.pre = cur 

        if self.count == self.max_count:
            self.result.append(cur.val)

        if self.count > self.max_count:
            self.max_count = self.count
            self.result = []
            self.result.append(cur.val)

        # right:
        self.traversal(cur.right)

    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        self.traversal(root)
        return self.result

三、236. 二叉树的最近公共祖先

本题其实是比较难的,可以先看我的视频讲解

1. 解题思路

自底向上遍历,第一个交汇的节点就是最近公共祖先。而二叉树只能从根节点开始遍历,但回溯的过程可以让我们从底向上去遍历树。

2. 后序遍历

        后序遍历:左右中的顺序,左/右中有p或q就向上返回,因此左子树中如果不为空,说明包含p或q,右子树不为空说明包含q或p,那么中间的这个节点就是最近的公共祖先。 

      

3. 代码实现

(1)定义函数traversal,返回值为二叉树的公共祖先,所以返回节点TreeNode。传入参数为根节点、p和q。

(2)终止条件:遍历的节点为空,直接返回null;如果root等于p或q,则将节点返回。

(3)后序遍历:

        左:向左遍历,传入left和q、p,告诉我们左子树是否存在p或q;

        右:向右遍历,传入right和q、p,告诉我们右子树是否存在p或q;

        中:如果左且右不为空,那么说明二者出现了p或q;如果左为空且右不为空,那么说明右子树出现了p或q,将右向上返回;如果左不为空且右为空,那么说明左子树出现了p或q,将左向上返回;左右均为空,返回null。

# 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':
        if root is None: return None
        if root == q or root == p: return root
        
        # left:
        left = self.lowestCommonAncestor(root.left, p, q)
        # right:
        right = self.lowestCommonAncestor(root.right, p, q)
        # middle:
        if left is None and right is None: return None
        if left is None and right is not None: return right
        if left is not None and right is None: return left
        if left is not None and right is not None: return root

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值