利用中序遍历解决二叉搜索树的问题。
530. 二叉搜索树的最小绝对差
二叉树遍历的双指针操作
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
# 利用
st = []
p = root
pre = -float('inf')
min_val = float('inf')
# 利用双指针,使得pre紧跟cur的值
while p is not None or st:
while p is not None:
st.append(p)
p = p.left
p = st.pop()
cur = p.val
if cur - pre < min_val:
min_val = cur - pre
pre = cur # 上一个节点的值
p = p.right
return min_val
# 伪代码
result = Max_len # 用全局变量记录相邻结点的最小值,递归函数中直接修改全局参数即可,所以递归函数不需要有返回值
pre = TreeNode()
def traversal(cur):
if not cur:
return
traversal(cur.left) # 左
if pre: # 中
result = min(result,cur.val-pre.val)
# pre如何紧跟着cur成为cur的前一个节点
pre = cur
# 右
traversal(cur.right)
我的思路(直白想法):
由于是二叉搜索树,所以可以利用中序遍历将二叉搜索树变成递增的序列,然后利用双指针的方式找到对应的最小差值。
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
# 按照左中右的中序顺序进行遍历
result = []
def dfs(node,result):
if not node:
return
dfs(node.left,result)
if node:
result.append(node.val)
dfs(node.right,result)
return result
result = dfs(root,result)
minValue = float('inf')
i,j = 0,1 # 利用双指针找到差值最小
while j <= len(result)-1:
if minValue > result[j] - result[i]:
minValue = result[j] - result[i]
i += 1
j += 1
return minValue
501. 二叉搜索树中的众数
双指针的思路:如果pre和cur相等那么对应的元素重复次数+1
反思: 全局变量需要以类内变量的形式出现
class Solution:
def __init__(self):
self.pre = TreeNode()
self.count = 0
self.max_count = 0
self.result = []
def search_BST(self, cur: TreeNode) -> None:
if not cur:
return None
self.search_BST(cur.left)
# 第一个节点
if not self.pre:
self.count = 1
# 与前一个节点数值相同
elif self.pre.val == cur.val:
self.count += 1
# 与前一个节点数值不相同
else:
self.count = 1
self.pre = cur
if self.count == self.max_count:
self.result.append(cur.val)
if self.count > self.max_count:
self.max_count = self.count
self.result = [cur.val] # 清空self.result,确保result之前的的元素都失效
self.search_BST(cur.right)
def findMode(self, root: TreeNode) -> List[int]:
if not root:
return None
self.search_BST(root)
return self.result
236. 二叉树的最近公共祖先
回溯: 需要将左右叶子结点中是否有p和q传入上一个结点中,左右子树都不为空则当前的父结点即为公共祖先。
那么如果采用回溯的方法,需要使用左右中后序遍历的方式。两种情况p&q是否在同一个枝叶的路径上。
// C++伪代码
TreeNode* traversal(root,q,p){
if(root==null) return null; // 如果遇到根节点直接返回
if(root==p || root==q): return root;
left = traversal(root.left,p,q) //告诉我们左子树中有没有出现p和q
right = traversal(root.right,p,q) //告诉我们左子树中有没有出现p和q
if left!= null && right != null:
return root //此时为公共祖先
if (left==null && right != null): //把右子树向上返回
return right;
else(right==null && left != null):
return left;
}
基本思路:返回左子树和右子树中是否出现过p或者q,如果出现过则把当前的这个结点返回给上一层结点。
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
def traversal(root,p,q):
=
if not root:
return None
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
# 非常关键的一步,不容易想。将含有两个结点的根结点传入上一层结点中,而不是任何时候传入的都是根节点。
if not left and right : return right
elif left and not right : return left
else: return None
return traversal(root,p,q)
补充:python知识点
python的字典排序
将python转化成元组类型的数据类型,然后使用sorted函数对元组列表进行排列即可。
d = {'a':1,'c':3,'b':2}
# d.items() 的返回值是dict_items([('a',1),('c',3),('b',2)])
# key表示按照哪一列进行排序
d_order = sorted(d.items(),key=lambda x:x[1],reverse = False)
print(d_order)
python中的局部变量与全局变量
函数中生成的变量均为局部变量,如果想要使用全局变量,需要将变量当成类内的属性。
- 局部变量: 当搜索一个标识符时,Python先从局部作用域开始搜索。如果在局部作用域内没有找到那个名字,那么一定会在全局域找到这个变量,否则会被抛出NameError异常。
- 全局变量: 全局变量的一个特征是除非删除掉,否则它们存活到脚本运行结束,且对于所有的函数,它们的值都是可以被访问的。
在函数中声明global函数即可达到,让函数中的变量成为全局变量的作用,此时改变函数体中的变量,相应的其他变量也会发生改变。
情况1: 外部没有定义x的值报错
情况2: 内部如果声明全局变量则此时不报错
情况3: 内部没有定义b就对b进行了运算故报错
情况4:在函数中声明全局变量,此时对应的函数不报错。
情况5: nonlocal声明在上级的局部作用域中,而不是全局定义,比如说在嵌套函数的情况下,利用nonloacl可以使得内部的变量作用到向外一层的函数中,但是如果声明的变量在上级局部变量中不存在,则会报错。