题目描述
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
提示:如果众数超过1个,不需考虑输出顺序
进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
算法思路
NAIVE
第一步,用字典来计数
class Solution:
def findMode(self, root: TreeNode):
if not root:return []
di=collections.defaultdict(int)
def bfs(root,di={}):
if not root:return []
di[root.val]+=1
bfs(root.left,di)
bfs(root.right,di)
bfs(root,di)
第二步,给字典按值排序,将众数放入列表
d1=sorted(di.items(), key=lambda x: x[1])
l,MAX=d1.pop()
ls=[]
ls.append(l)
第三步,根据最大值判断是否还有其他众数。
while d1:
if d1[-1][1]==MAX:
ls.append(d1.pop()[0])
else:break
return ls
执行用时 :60 ms, 在所有 Python3 提交中击败了80.28%的用户
值得一提的是这种方法适合求所有树的众数。
IMPROVE
基于搜索树的中序遍历是递增数组,由此思想可得仅使用O(1)空间的方法。
class Solution:
def findMode(self, root: TreeNode):
if not root:return []
res=[]
pro=None
curtime,maxtime=1,0
def inorder(root):
nonlocal pro
nonlocal curtime
nonlocal maxtime
if not root:return
inorder(root.left)
if pro:
if root.val == pro.val:curtime+=1
else:curtime=1
pro = root
if curtime==maxtime:res.append(root.val)
elif curtime>maxtime:
res.clear()
res.append(root.val)
maxtime=curtime
inorder(root.right)
inorder(root)
return res
!res是序列,可以直接修改。
!必须要提的是本来是把前一个节点pro放在定义的inorder函数里的,但是对于测例[1,None,2,2],永远在从第三层的2跳回到第二层的2那里时,pro变成了指向根节点1. 所以输出值总是[1,2,2]
一直不知道原因!气死。我还是没完全掌握递归的内在。
解决方法:将储存前置值的pro变量变成内嵌函数外的外部函数的变量,通过nonlocal声明来修改。
补充一下,后来发现curtime,maxtime也跳反,一气之下都声明成外部变量。
!关于如上问题,结合递归的定义,可能是内嵌函数的所有变量都在递归调用时将当时的状态push进栈里,即使在下一层做了修改,当栈返回时都恢复了当初的状态。
!
if pro:
if root.val == pro.val:curtime+=1
else:curtime=1
可以替换为
if pro:curtime=curtime+1 if root.val == pro.val else 1
执行用时 :52 ms, 在所有 Python3 提交中击败了97.21%的用户