更弱智的算法学习 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
相关推荐
Tingjct3 分钟前
【初阶数据结构-二叉树】
c语言·开发语言·数据结构·算法
C雨后彩虹3 分钟前
计算疫情扩散时间
java·数据结构·算法·华为·面试
yyy(十一月限定版)1 小时前
寒假集训4——二分排序
算法
星火开发设计1 小时前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识
醉颜凉1 小时前
【LeetCode】打家劫舍III
c语言·算法·leetcode·树 深度优先搜索·动态规划 二叉树
达文汐1 小时前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗1 小时前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
User_芊芊君子1 小时前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
算法_小学生1 小时前
LeetCode 热题 100(分享最简单易懂的Python代码!)
python·算法·leetcode
执着2591 小时前
力扣hot100 - 234、回文链表
算法·leetcode·链表