给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
- 结点左子树中所含结点的值小于等于当前结点的值
- 结点右子树中所含结点的值大于等于当前结点的值
- 左子树和右子树都是二叉搜索树
例如:
给定 BST [1,null,2,2],
返回[2].
提示:如果众数超过1个,不需考虑输出顺序
进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
思路:
注:如果不是二叉搜索树,而是普通二叉树,方法为:
先把树全部遍历一遍,用什么顺序遍历都可以,统计元素频率,把统计出来的出现频率(map中的value排序)。
# 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
from collections import defaultdict
class Solution:
def searchBST(self, cur, freq_map):
if cur is None:
return
freq_map[cur.val] += 1 # 统计元素频率
self.searchBST(cur.left, freq_map)
self.searchBST(cur.right, freq_map)
def findMode(self, root):
freq_map = defaultdict(int) # key:元素,value:出现频率
result = []
if root is None:
return result
self.searchBST(root, freq_map)
max_freq = max(freq_map.values())
for key, freq in freq_map.items():
if freq == max_freq:
result.append(key)
return result
二叉搜索树:
双指针,中序遍历
cur如果和pre的value相等,count += 1,
直到cur与pre不相等,count = 1,重新来。
如果count等于maxCount(最大频率),把这个元素加入到结果集中。
当频率count大于maxCount的时候,不仅要更新maxCount,而且要清空结果集,因为结果集之前的元素都失效了。把新的元素加入到结果集中。
class Solution:
def __init__(self):
self.maxCount = 0 # 最大频率,用于记录BST中某个元素出现的最大频率
self.count = 0 # 当前元素的频率计数
self.pre = None # 记录上一个遍历的节点
self.result = [] # 存储出现频率最高的元素
def searchBST(self, cur):
if cur is None:
return
self.searchBST(cur.left) # 遍历左子树
# 中序遍历当前节点
if self.pre is None: # 如果是遍历的第一个节点
self.count = 1
elif self.pre.val == cur.val: # 如果当前节点值与前一个节点值相同
self.count += 1
else: # 如果当前节点值与前一个节点值不同
self.count = 1
self.pre = cur # 更新上一个遍历的节点
if self.count == self.maxCount: # 如果当前元素的频率等于最大频率
self.result.append(cur.val) # 将当前元素添加到结果列表中
if self.count > self.maxCount: # 如果当前元素的频率大于最大频率
self.maxCount = self.count # 更新最大频率
self.result = [cur.val] # 清空结果列表,并将当前元素作为唯一元素添加进去
self.searchBST(cur.right) # 遍历右子树
return
def findMode(self, root):
self.count = 0
self.maxCount = 0
self.pre = None # 初始化上一个节点为空
self.result = [] # 初始化结果列表为空
self.searchBST(root) # 开始中序遍历
return self.result # 返回出现频率最高的元素列表
讲解:
-
类的初始化:
__init__
方法初始化了一些变量:maxCount
用于记录BST中某个元素出现的最大频率,count
用于当前元素的频率计数,pre
用于记录上一个遍历的节点,result
用于存储出现频率最高的元素。
-
中序遍历搜索方法
searchBST
:- 这个方法对BST进行中序遍历(左-中-右顺序),以确保遍历的结果是一个递增序列。
if cur is None: return
:如果当前节点为空,则直接返回。self.searchBST(cur.left)
:首先递归遍历左子树。- 然后处理中间节点:
- 如果
self.pre
为空,说明这是第一个遍历的节点,将count
设为1。 - 如果当前节点值等于前一个节点值,说明出现了相同的值,频率计数
count
增加1。 - 如果当前节点值不等于前一个节点值,重置频率计数
count
为1。 - 更新
self.pre
为当前节点。
- 如果
- 根据当前频率计数
count
和最大频率maxCount
的关系,更新结果列表result
:- 如果
count
等于maxCount
,将当前节点值添加到result
列表中。 - 如果
count
大于maxCount
,更新maxCount
并重置result
列表,仅包含当前节点值。
- 如果
- 最后递归遍历右子树
self.searchBST(cur.right)
。
-
寻找众数方法
findMode
:- 这个方法是寻找BST中的众数的入口方法。
- 在调用中序遍历方法
searchBST
前,初始化所有变量。 - 调用
searchBST
方法开始遍历BST。 - 返回结果列表
result
,其中包含了出现频率最高的元素。