Leetcode-树
98. 验证二叉搜索树 https://leetcode-cn.com/problems/validate-binary-search-tree/
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
假设一个二叉搜索树具有如下特征:
节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
解:
中序遍历二叉排序树,判断得到的数组是否是升序。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
inorder = self.inorder(root)
return inorder == sorted(set(inorder)) # 这里要注意判重
def inorder(self, root):
if root is None:
return []
return self.inorder(root.left) + [root.val] + self.inorder(root.right)
但是这个效率是相对较低的,想办法改进一下,不用完整保留中序遍历的结果,只需要比较中序遍历时当前节点和前驱节点即可
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
self.prev = None
return self.helper(root)
def helper(self, root):
if root is None:
return True
if not self.helper(root.left): # 如果左子树不是二叉搜索树,那root也不是
return False
if self.prev and self.prev.val >= root.val: # 如果左子树是二叉搜索树,比较root和其前驱节点值,如果前驱大,root不是二叉搜索树
return False
self.prev = root # 如果满足root比前驱大,下面去检查右子树,在此之前要先把前驱节点更新为root
return self.helper(root.right)
直接递归来判断
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
if root is None:
return True
if root.left is None and root.right is None:
return True
flag = True
if root.left:
if not self.isValidBST(root.left):
flag = False
# 左子树的最大,一直向右即可
l = root.left
while l.right:
l = l.right
if root.val <= l.val:
flag = False
if root.right:
if not self.isValidBST(root.right):
flag = False
# 右子树的最小,一直向左即可
r = root.right
while r.left:
r = r.left
if root.val >= r.val:
flag = False
return flag
这个递归写的也是比较冗余的,有很多重复搜索。再简化一下,每次都把节点和其上下界比较(如果有的话)。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
return self.isValid(root)
def isValid(self, root, lower=float('-inf'), upper=float('inf')):
if root is None:
return True
val = root.val
if lower is not None and val <= lower:
return False
if upper is not None and val >= upper:
return False
if not self.isValid(root.left, lower, val):
return False
if not self.isValid(root.right, val, upper):
return False
return True
235. 二叉搜索树的最近公共祖先 https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉搜索树中。
解:
迭代,从根节点往下,如果根节点比两个节点都大,说明两个节点在根节点的左子树中;如果根节点比两个节点都小,说明两个节点在根节点的右子树中。更新根节点即可。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root:
return None
if root.left is None and root.right is None:
return root
ans = root
while ans:
if ans.val < p.val and ans.val < q.val:
ans = ans.right
elif ans.val > p.val and ans.val > q.val:
ans = ans.left
else:
return ans
递归实现,空间复杂度O(N)。这题其实没必要用递归
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if root.val < p.val and root.val < q.val:
return self.lowestCommonAncestor(root.right, p, q) # p、q比root都大,需要去root右子树查找
if root.val > p.val and root.val > q.val:
return self.lowestCommonAncestor(root.left, p, q)
return root
236.二叉树的最近公共祖先 https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
解:
递归,从根节点开始向下,如果root就是p或者q,那么公共祖先就是root,否则的话分别去左右子树查找p和q,如果p、q都在左子树,递归的去左子树向下查找;如果p、q都在右子树,递归的去右子树查找;如果p、q各在一边,那么root
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if root is None or root is q or root is p:
return root
left = self.lowestCommonAncestor(root.left, p, q) # 分别去左右子树查找p和q
right = self.lowestCommonAncestor(root.right, p, q)
if left is None: # 如果p、q都不在左子树,返回右子树的查找结果
return right
elif right is None: # 如果p、q都不在右子树,返回左子树的查找结果
return left
return root # 如果p和q各在左右一边,公共祖先就是当前root
使用父指针迭代,找出 p 和 q 的各自到根节点的路径。如果每个节点都有父指针,可以从 p 和 q 返回以获取它们的祖先。在这个遍历过程中,得到的第一个公共节点是 LCA 节点。可以在遍历树时将父指针保存在字典中。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
parent = {root: None}
stack = [root]
# 只要没有把p、q都找到,就继续向下遍历树,继续找
while p not in parent or q not in parent:
node = stack.pop()
if node.left:
parent[node.left] = node
stack.append(node.left)
if node.right:
parent[node.right] = node
stack.append(node.right)
ancestors = set() # 按父指针遍历p的祖先
while p:
ancestors.add(p)
p = parent[p]
while q not in ancestors: # 找p、q公共的祖先
q = parent[q]
return q

浙公网安备 33010602011771号