更弱智的算法学习 day18

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

一开始想错了,想着对于二叉搜索树来说,最小差值肯定在父节点和左右子节点之间产生,实际上,根据搜索树的性质,其中序遍历就是一个递增数组,直接在数组中处理就可以了

在递归过程中,用户在每个节点处只计算了当前节点与左右子节点的差的绝对值,但实际上,在二叉搜索树中,最小差值不一定出现在父子节点之间,也可能出现在祖先和后代之间,但由于二叉搜索树的性质,最小差值一定出现在相邻的中序遍历节点之间。

python 复制代码
# 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.maxdiff = 10**5+1
        self.res = []
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        self.traversal(root, self.res)
        for i in range(len(self.res)-1):
            diff = self.res[i+1] - self.res[i]
            self.maxdiff = min(diff, self.maxdiff)
        return self.maxdiff

    def traversal(self, root, res):
        if not root:
            return
        self.traversal(root.left, res)
        self.res.append(root.val)
        self.traversal(root.right, res)
        
        

501.二叉搜索树中的众数

这个题目可以转化为收集到中序的序列数据,然后对此序列寻找众数。然而如何寻找众数呢?

  • self.res[i] == self.res[i-1]时,说明当前数值与前一个相同,current_count加1。

  • 当遇到一个不同的数值时,说明前一个数值的连续序列结束了。此时,调用 update_modes方法来判断这个刚刚结束统计的数值是否是众数

  • update_modes方法根据当前数值的计数 (count) 与当前已知的最大计数 (self.maxcount) 进行比较:

    如果 count > self.maxcount:这意味着发现了出现次数更多的数。此时,将 self.maxcount更新为这个更大的 count,并清空之前的众数列表 self.out,然后将这个新的众数 val加入列表。

    如果 count == self.maxcount:这意味着发现了一个出现次数和当前众数一样多的数。此时,只需将这个数 val追加到众数列表 self.out中即可。

python 复制代码
# 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.res = []
        self.maxcount = 0
        self.out = []


    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        self.traversal(root,self.res)
        current_val = self.res[0]
        current_count = 1

        for i in range(1, len(self.res)):
            if self.res[i] == self.res[i-1]:
                current_count += 1
            else:
                self.update_modes(current_val, current_count)
                current_val = self.res[i]
                current_count = 1
        self.update_modes(current_val, current_count)

        return self.out

    def update_modes(self, val, count):
        """更新众数列表"""
        if count > self.maxcount:
            self.maxcount = count
            self.out = [val]  # 清空之前的结果,重新开始
        elif count == self.maxcount:
            self.out.append(val)  # 相同频率,追加到结果

    def traversal(self, root, res):
        if not root:
            return
        self.traversal(root.left, res)
        self.res.append(root.val)
        self.traversal(root.right, res)

学习了一下不需要额外空间的写法,感觉总体来说区别不太大。

python 复制代码
# 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.max_count = 0
        self.cur_count = 0
        self.pre_value = None
        self.res = []

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

    def traversal(self, root):
        if not root:
            return
        self.traversal(root.left)

        if root.val != self.pre_value: #与前一个节点不同的情况
            self.cur_count = 1
            self.pre_value = root.val
        else:
            self.cur_count += 1
        
        if self.cur_count > self.max_count:
            self.res = [root.val]
            self.max_count = self.cur_count
        elif self.cur_count == self.max_count:
            self.res.append(root.val)
        
        self.traversal(root.right)

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

总体思想比较好懂,也即分类讨论。

考虑p和q的位置,如果从当前节点看,p和q分别在左右子树里,那么最近公共祖先就是自己,也即root;如果仅左子树或右子树有,那么在存在的那一侧返回;如果都不存在,则返回None,表示既没找到p和q,也算不出最近公共祖先。

复杂的点在于返回值的异质性,即返回"有没有找到p和q",也返回"有没有算出最近公共祖先",理解是当左右子树返回都是非空节点时,此时返回的就是最近公共祖先,再次之前,返回的都是,这里是否有p或q的判断

python 复制代码
# 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 not root:
            return None

        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)

        if root == p or root == q or left and right:
            return root
        if right:
            return right
        if left:
            return left

补充一下二叉搜索树的最近公共祖先

二叉搜索树的最近公共祖先由于大小排序,可以轻松知道本节点视角下的p和q的位置

python 复制代码
# 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':
        value = root.val
        if p.val < value and q.val < value:
            return self.lowestCommonAncestor(root.left, p, q)
        elif p.val > value and q.val > value:
            return self.lowestCommonAncestor(root.right, p, q)
        else:
            return root
相关推荐
用户0203388613143 分钟前
红黑树主要功能实现
算法
叫我:松哥5 分钟前
基于 Flask 框架开发的在线学习平台,集成人工智能技术,提供分类练习、随机练习、智能推荐等多种学习模式
人工智能·后端·python·学习·信息可视化·flask·推荐算法
专注VB编程开发20年8 分钟前
压栈顺序是反向(从右往左)的,但正因为是反向压栈,所以第一个参数反而离栈顶(ESP)最近。
java·开发语言·算法
Xの哲學9 分钟前
Linux Select 工作原理深度剖析: 从设计思想到实现细节
linux·服务器·网络·算法·边缘计算
东心十12 分钟前
AI学习环境安装
人工智能·学习
Hooray1121 分钟前
入门_本地项目上传到GitCode上面
学习·gitcode
Paul_092028 分钟前
golang编程题
开发语言·算法·golang
名字不相符28 分钟前
NSSCTF2026年1月8日每日一练之[第五空间 2021]WebFTP
学习·萌新
四谎真好看31 分钟前
JavaWeb 学习笔记(Day02)之Vue
笔记·学习·vue·学习笔记·javaweb
颜酱32 分钟前
用填充表格法-继续吃透完全背包及其变形
前端·后端·算法