501. 二叉搜索树中的众数

给定一个二叉搜索树,找到其中的众数,即出现频率最高的元素。题目要求不使用额外空间且进阶条件下考虑递归调用栈开销。

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

给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。

假定 BST 有如下定义:

  • 结点左子树中所含结点的值小于等于当前结点的值
  • 结点右子树中所含结点的值大于等于当前结点的值
  • 左子树和右子树都是二叉搜索树

例如:
给定 BST [1,null,2,2],

   1
    \
     2
    /
   2

返回[2].

提示:如果众数超过1个,不需考虑输出顺序

进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution:
    # res = []
    # count = {}
    '''
    直接点思路就是利用一个哈希表来记录数字和其出现次数之前的映射,
    然后维护一个变量mx来记录当前最多的次数值,这样在遍历完树之后,
    根据这个mx值就能把对应的元素找出来。
    那么用这种方法的话就不需要用到二分搜索树的性质了,随意一种遍历方式都可以
    '''
    def findMode(self, root: TreeNode) -> 'List[int]':
        if root is None:
            return []
        # 之前将下面两个初始化放在了Solution类里面,结果oj连续测试时,保存了上一次测试的结果,因此没通过;
        res = []
        count = {}
        self.midOder(root, count)
        cont = max(count.values())
        for k in count.keys():
            if count[k] == cont:
                res.append(k)
        return res


    def midOder(self, root: TreeNode, count:dict) -> TreeNode:
        if root is None:
            return root

        if root.left:
            self.midOder(root.left, count)

        if root.val not in count:
            count[root.val] = 1
        else:
            count[root.val] += 1

        if root.right:
            self.midOder(root.right, count)

    # 非递归
    def findMode2(self, root: TreeNode) -> 'List[int]':

        if not root: return []
        d = {root.val: 1}

        stack = [root]

        while stack:
            node = stack.pop()
            # print(node.val)
            if node.left:
                if node.left.val in d:
                    d[node.left.val] += 1
                else:
                    d[node.left.val] = 1
                stack.append(node.left)
            # print(stack, d)
            if node.right:
                if node.right.val in d:
                    d[node.right.val] += 1
                else:
                    d[node.right.val] = 1
                stack.append(node.right)

        mode = sorted(d.items(), key=lambda d: d[1])[-1][1]

        return [x for x in d if d[x] == mode]

    '''
    不用除了递归中的隐含栈之外的额外空间,那么我们就不能用哈希表了,
    二分搜索树,那么我们中序遍历出来的结果就是有序的,这样我们只要比较前后两个元素是否相等,
    就等统计出现某个元素出现的次数,因为相同的元素肯定是都在一起的。
    '''

    def findMode3(self, root: 'TreeNode') -> 'List[int]':
        res = []
        self.mx = 0  # 最大相同节点个数
        self.cnt = 0  # 当前相同节点个数
        self.pre = None
        self.inorder(root, res)
        return res

    def inorder(self, root, res: list):
        if not root:
            return
        self.inorder(root.left, res)

        if self.pre:
            self.cnt = self.cnt + 1 if (self.pre.val == root.val) else 1
        else:
            self.cnt = 1

        if self.cnt >= self.mx:
            if self.cnt > self.mx:
                res.clear()
            res.append(root.val)
            self.mx = self.cnt

        self.pre = root
        self.inorder(root.right, res)


if __name__ == '__main__':
    s = Solution()
    root = TreeNode(5)
    root.left = TreeNode(4)
    root.left.left = TreeNode(4)
    root.right = TreeNode(7)
    root.right.left = TreeNode(7)
    root.right.right = TreeNode(8)
    print(s.findMode3(root))
    '''
    5
   / \
  4   7
 /   /  \
4   7    8
    '''

这个系统输出什么是这样的结果,我一直以为自己错了,提交之后发现通过了!!!why ???

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值