目录
Leetcode - 530
暴力法就是先中序遍历出一个序列,然后用双指针求相邻元素差的绝对值。
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
res = []
def traversal(root):
nonlocal res
if not root:
return None
traversal(root.left)
res.append(root.val)
traversal(root.right)
traversal(root)
minValue = float("INF")
i =0
j = i+1
while j < len(res):
gap = abs(res[j] - res[i])
if gap < minValue:
minValue = gap
j+=1
i+=1
return minValue
另一个方法,递归,对于这种二叉搜索树,依然用中序遍历,此处是定义一个node来指向root的上一个节点,然后让node和root的值做差并记录,和验证二叉树那题的思路一样
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
minGap = float("INF")
node = None
def traversal(root):
nonlocal node,minGap
if not root:
return
traversal(root.left)
if node != None:
minGap = min(minGap,abs(node.val - root.val))
node = root
traversal(root.right)
traversal(root)
return minGap
Leetcode - 501
首先是暴力法,先中序遍历,然后统计词频再返回结果,很简单,代码就不放了。
另一种 递归法,这里首先说几个全局变量,count用于记录当前节点的频数,maxCount用于记录最大频数,res用于存结果,node用于指向root的上一个节点。
这里首先要注意的是 此处记录频数不能使用node来记录,要使用root指向的节点来统计频数,若使用node记录,则会忽略掉树中的最后一个节点。 再就是count>maxCount时,res要清空。
还有遇到node.val != root.val时,因为是用root来记录节点,所以此时要将count重新置为1,用于为新的一个节点记录频数。
这里三点我都想到了,但是还是没能ac,重点就是一开始,node==None时的逻辑,此时node和root没法进行比较,这里直接count = 1即可,为第一个节点计数。当node.val==root.val时,count+=1,当两者不等时,重置count=1,注意这里的三个条件是平行的
当这些进行完后,再进行count和maxCount的比较,若count小 不管,两者相等,append,count更大,清空res,并append root.val ,然后跟新maxCount的值
def findMode(self, root: Optional[TreeNode]) -> List[int]:
res = []
count = 0
maxCount = 0
node = None
def traversal(root):
nonlocal count,maxCount,res,node
if not root:
return
traversal(root.left)
if node == None:
count = 1
elif node.val == root.val:
count += 1
elif node.val != root.val:
count = 1
if count == maxCount:
res.append(root.val)
elif count > maxCount:
res = []
res.append(root.val)
maxCount = count
node = root
traversal(root.right)
traversal(root)
return res
Leetcode - 236
首先确定遍历顺序,这题是找两个节点的最近公共祖先,那肯定是从下往上的,从下往上就是后序遍历,这题是返回祖先,所以递归是有返回值的,且进行左右遍历的时候肯定都需要定义一个变量来接收结果,递归终止的时候也需要返回值,这里要和没有返回值的递归区分开,没有返回值时左右子树遍历还有递归终止(直接return就行)都不需要返回值
首先 递归函数参数: root,p,q
终止条件: root为空直接return root(None),若root为p,q其中一个直接返回root。
然后是左右子树递归,返回值分别用left和right接受,再到中的处理逻辑:若left和right同时不为空说明当前的root就是我们要求的最近公共祖先,若left和right其中有一个不为空,那么将这一个返回,若同时为空返回None。
这里分两种情况讨论:1. p,q分别在不同子树上,left和right分别是在root的左子树和右子树中递归返回的结果,若均不为空,则说明能在两个子树中将这两个节点找到,又因为是从下往上遍历的,所以这里root就是最近的公共祖先。 2 p是q的祖先或者q是p的祖先,这里以p为祖先为例,p会先被找到所以会被先作为结果返回,直接用P向上传递。
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
def traversal(root,p,q):
if root == None:
return root
if root == p or root == q:
return root
left = traversal(root.left,p,q)
right = traversal(root.right,p,q)
if left and right:
return root
elif left == None and right != None:
return right
elif left !=None and right == None:
return left
else:
return None
return traversal(root,p,q)