代码随想录Day17 | Leetcode530 二叉搜索树的最小绝对差 、Leetcode501 二叉搜索树中的众数、Leetcode700 二叉的最近公共祖先

代码随想录系列

代码随想录 Day1 | Leetcode704 二分查找、Leetcode27 移除元素_(i+j)/2越界-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135234321?spm=1001.2014.3001.5502代码随想录 Day2 | Leetcode997 有序数组的平方、Leetcode209 长的最小的子数组、Leetcode59 螺旋矩阵2-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135259254?spm=1001.2014.3001.5502代码随想录 Day3 | Leetcode203 移除链表元素、Leetcode707 设计链表、Leetcode206反转链表-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135331420?spm=1001.2014.3001.5502代码随想录 Day4 | Leetcode24 两两交换链表中的节点、Leetcode19 删除链表的倒数第N个节点、面试题 02.07 链表相交、Leetcode142 环形链表II-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135376417?spm=1001.2014.3001.5502代码随想录 Day5 | Leetcode242 有效的字母异位词 、Leetcode349 两个数组的交集、Leetcode202 快乐数、Leetcode1 两数之和-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135420816?spm=1001.2014.3001.5502代码随想录 Day6 | Leetcode454 四数相加、Leetcode383 赎金信、Leetcode15 三数之和、Leetcode18 四数之和-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135447496?spm=1001.2014.3001.5502代码随想录 Day7 | Leetcode344 反转字符串、Leetcode541 反转字符串2、卡码网54 替换数字、Leetcode151 翻转字符串里的单词、卡码网55 左右旋转字符串_python给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135469022?spm=1001.2014.3001.5502代码随想录 Day8 | Leetcode22 用栈实现队列、Leetcode225 用队列实现栈-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135492707?spm=1001.2014.3001.5502代码随想录 Day9 | Leetcode20 有效的括号、Leetcode541 删除字符串中的所有相邻重复项 | Leetcode150 逆波兰表达式求值-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135515537?spm=1001.2014.3001.5502代码随想录 Day10 | Leetcode239 滑动窗口最大值、Leetcode 347 前 K 个高频元素-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135542134?spm=1001.2014.3001.5502代码随想录 Day11 | Leetcode144 二叉树的前序遍历、Leetcode145 二叉树的后序遍历、Leetcode94 二叉树的中序遍历-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135614330?spm=1001.2014.3001.5502代码随想录Day12 二叉树层序遍历| Leetcode十题-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135638685?spm=1001.2014.3001.5502代码随想录 Day13 | Leetcode111 二叉树的最小深度、Leetcode222 完全二叉树的节点个数、Leetcode104 二叉树的最大深度、Leetcode559 N叉树的最大深度-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135738461?spm=1001.2014.3001.5502代码随想录 Day14 | Leetcode110 平衡二叉树、Leetcode257 二叉树的所有路径、Leetcode404 左叶子之和-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135803577?spm=1001.2014.3001.5502代码随想录 Day15 | Leetcode105、Leetcode106、Leetcode112、Leetcode113、Leetcode513-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135856991?spm=1001.2014.3001.5502代码随想录 Day16 | Leetcode654 最大二叉树、Leetcode617 合并二叉树、Leetcode700 二叉搜索树中的搜索、Leetcode98 验证二叉搜索树-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_41502639/article/details/135944102?spm=1001.2014.3001.5502

上题 

530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)

501. 二叉搜索树中的众数 - 力扣(LeetCode)

236. 二叉树的最近公共祖先 - 力扣(LeetCode)

第一题

    给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
    差值是一个正数,其数值等于两值之差的绝对值。

    示例 1:
    输入:root = [4,2,6,1,3]
    输出:1

    示例 2:
    输入:root = [1,0,48,null,null,12,49]
    输出:1

思路

搜索树左子树<结点<右子树,差值最小一定会是相邻两个结点之间出现,使用中序遍历

代码

import collections
from math import inf


class TreeNode:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


class Solution:
    """
    给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
    差值是一个正数,其数值等于两值之差的绝对值。

    示例 1:
    输入:root = [4,2,6,1,3]
    输出:1

    示例 2:
    输入:root = [1,0,48,null,null,12,49]
    输出:1
    """

    def create_tree(self, root):
        if not root:
            return None
        result = TreeNode(root[0])
        queue = [result]
        i, n = 1, len(root)

        while i < n and queue:
            node = queue.pop(0)
            if i < n and root[i] != 'null':
                root_node = TreeNode(root[i])
                queue.append(root_node)
                node.left = root_node
            i += 1

            if i < n and root[i] != 'null':
                root_node = TreeNode(root[i])
                queue.append(root_node)
                node.right = root_node
            i += 1

        return result

    def getMinimumDifference1(self, root) -> int:
        if not root:
            return
        stack = []
        result = inf
        pre = None
        while root or stack:
            if root:
                stack.append(root)
                root = root.left
            else:
                node = stack.pop()
                if pre:
                    result = min(abs(node.val-pre.val), result)
                pre = node
                root = node.right
        return result

    def getMinimumDifference(self, root) -> int:
        if not root:
            return
        re = []
        result = inf
        self.inorder(root, re)
        for i in range(1, len(re)):
            result = min(abs(re[i]-re[i-1]), result)
        return result


    def inorder(self, root, result):
        if not root:
            return
        self.inorder(root.left, result)
        result.append(root.val)
        self.inorder(root.right, result)


if __name__ == '__main__':
    test = Solution()
    root = [[4, 2, 6, 1, 3], [1, 0, 48, 'null', 'null', 12, 49]]
    for i in root:
        tree = test.create_tree(i)
        print(test.getMinimumDifference(tree), test.getMinimumDifference1(tree))

第二题

    给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
    如果树中有不止一个众数,可以按 任意顺序 返回。

    假定 BST 满足如下定义:
    结点左子树中所含节点的值 小于等于 当前节点的值
    结点右子树中所含节点的值 大于等于 当前节点的值
    左子树和右子树都是二叉搜索树


    示例 1:
    输入:root = [1,null,2,2]
    输出:[2]

    示例 2:
    输入:root = [0]
    输出:[0]

思路

同上第一题,二叉搜索树使用中序遍历得到的是递增的有序序列,众数一定会相邻,如果相邻两个数不相等,则这个数一定不是众数

代码

import collections
from math import inf


class TreeNode:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


class Solution:
    """
    给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
    如果树中有不止一个众数,可以按 任意顺序 返回。

    假定 BST 满足如下定义:
    结点左子树中所含节点的值 小于等于 当前节点的值
    结点右子树中所含节点的值 大于等于 当前节点的值
    左子树和右子树都是二叉搜索树


    示例 1:
    输入:root = [1,null,2,2]
    输出:[2]

    示例 2:
    输入:root = [0]
    输出:[0]
    """

    def create_tree(self, root):
        if not root:
            return None
        result = TreeNode(root[0])
        queue = [result]
        i, n = 1, len(root)

        while i < n and queue:
            node = queue.pop(0)
            if i < n and root[i] != 'null':
                root_node = TreeNode(root[i])
                queue.append(root_node)
                node.left = root_node
            i += 1

            if i < n and root[i] != 'null':
                root_node = TreeNode(root[i])
                queue.append(root_node)
                node.right = root_node
            i += 1

        return result

    def findMode1(self, root):
        """
        迭代
        """
        if not root:
            return
        result = []
        stack = []
        pre = None
        con, max_con = 0, 0
        while root or stack:
            if root:
                stack.append(root)
                root = root.left
            else:
                node = stack.pop()
                # 搜索树中序遍历是一个递增有序序列,出现众数只会在相邻节点
                if pre and pre.val == node.val:
                    con += 1
                else:
                    con = 1
                if con == max_con:
                    result.append(node.val)
                elif con > max_con:
                    result = [node.val]
                    max_con += 1
                pre = node
                root = node.right
        return result

    def findMode(self, root):
        """
        递归
        """
        if not root:
            return
        re = []
        con, max_con = 1, 1
        self.inorder(root, re)
        result = [re[0]]
        pre = re[0]

        for i in range(1, len(re)):
            node = re[i]
            if pre == node:
                con += 1
            else:
                con = 1
            if con == max_con:
                result.append(node)
            elif con > max_con:
                max_con = con
                result = [node]
            pre = node
        return result

    def inorder(self, root, result):
        if not root:
            return
        self.inorder(root.left, result)
        result.append(root.val)
        self.inorder(root.right, result)


if __name__ == '__main__':
    test = Solution()
    root = [[1, 'null', 2, 2], [0]]
    for i in root:
        tree = test.create_tree(i)
        print(test.findMode(tree), test.findMode1(tree))

第三题

    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
    百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

    示例 1:
    输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
    输出:3
    解释:节点 5 和节点 1 的最近公共祖先是节点 3 。

    示例 2:
    输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
    输出:5
    解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。

    示例 3:
    输入:root = [1,2], p = 1, q = 2
    输出:1

思路

1.root等于p或q,则root即为所求
2.递归找左右子树
3.左子树找不到时:右子树可能找不到也可能找到,不管哪种情况直接返回右子树的结果即可
4. 右子树找不到时:左子树可能找不到也可能找到,不管哪种情况直接返回左子树的结果即可
5.左右子树的查询均不为空,则当前结点即为p、q的公共祖先节点
6.前序遍历

代码 

本地调试容易犯错的是把p、q当作数值传递,实际上p、q是树结点

import collections
from math import inf


class TreeNode:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


class Solution:
    """
    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
    百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

    示例 1:
    输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
    输出:3
    解释:节点 5 和节点 1 的最近公共祖先是节点 3 。

    示例 2:
    输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
    输出:5
    解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。

    示例 3:
    输入:root = [1,2], p = 1, q = 2
    输出:1
    """

    def create_tree(self, root):
        if not root:
            return None
        result = TreeNode(root[0])
        queue = [result]
        i, n = 1, len(root)

        while i < n and queue:
            node = queue.pop(0)
            if i < n and root[i] != 'null':
                root_node = TreeNode(root[i])
                queue.append(root_node)
                node.left = root_node
            i += 1

            if i < n and root[i] != 'null':
                root_node = TreeNode(root[i])
                queue.append(root_node)
                node.right = root_node
            i += 1

        return result

    def lowestCommonAncestor(self, root, p, q):
        """
        1.root等于p或q,则root即为所求
        2.递归找左右子树
        3.左子树找不到时:右子树可能找不到也可能找到,不管哪种情况直接返回右子树的结果即可
        4. 右子树找不到时:左子树可能找不到也可能找到,不管哪种情况直接返回左子树的结果即可
        5.左右子树的查询均不为空,则当前结点即为p、q的公共祖先节点
        6.前序遍历
        """
        if not root or root == p or root == q:
            return root
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        if not left:
            return right
        if not right:
            return left
        return root

    def find_node_by_val(self, node, val):
        if node is None:
            return None
        if node.val == val:
            return node
        return self.find_node_by_val(node.left, val) or self.find_node_by_val(node.right, val)


if __name__ == '__main__':
    test = Solution()
    root = [[3, 5, 1, 6, 2, 0, 8, 'null', 'null', 7, 4], [3, 5, 1, 6, 2, 0, 8, 'null', 'null', 7, 4], [1, 2]]
    p = [5, 5, 1]
    q = [1, 4, 2]
    for i in range(len(root)):
        tree = test.create_tree(root[i])
        p_node = test.find_node_by_val(tree, p[i])
        q_node = test.find_node_by_val(tree, q[i])
        print(test.lowestCommonAncestor(tree, p_node, q_node).val)

总结

不要懈怠

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值