文章目录
基本操作类题目
235. 二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。
按照最近公共祖先的定义,我们可以知道p、q、root为下面三种情况之一:
- p、q在root的左右子树中
- p = root,q在root的左右子树中
- q = root,p在root的左右子树中
思路1:迭代搜索
- 当节点root为空时跳出;
- 当p,q都在root的右子树中,则遍历至root.right ;否则,当p,q都在root的左子树中,则遍历至root.left;否则,说明找到了最近公共祖先,跳出。
返回值:最近公共祖先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':
cur_node = root
# 迭代循环搜索
while cur_node:
# 如果p,q都在左子树中
if p.val < cur_node.val and q.val < cur_node.val:
cur_node = cur_node.left
# 如果p,q都在右子树中
elif p.val > cur_node.val and q.val > cur_node.val:
cur_node = cur_node.right
# 如果p,q分别在左子树与右子树中,则返回当前节点
else:
return cur_node
思路2:递归
- 当p,q都在root的右子树中,则开启递归root.right并返回;否则,
- 当p,q都在root的左子树中,则开启递归root.left 并返回;
返回值:最近公共祖先 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 p.val > root.val and q.val > root.val:
return self.lowestCommonAncestor(root.right,p,q)
elif p.val < root.val and q.val < root.val:
return self.lowestCommonAncestor(root.left,p,q)
else:
return root
450. 删除二叉搜索树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。
示例:
思路:
理解这个算法的关键在于保持BST中序遍历的顺序性。
删除一个节点会有三种情况:
- 待删除的节点左子树为空,此时,让待删除节点的右子树代替它即可
- 待删除的节点右子树为空,此时,让待删除节点的左子树代替它即可
- 待删除节点的左右子树都不为空,则可以有两种处理方式:
- 让待删除节点的前驱结点带她它
2.让待删除节点的后继节点代替它
# 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
class Solution:
def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
# 如果根节点为空,返回None
if root == None:
return root
# 递归调用左子树,寻找等于key的值
if key < root.val:
root.left = self.deleteNode(root.left,key)
return root
# 递归调用右子树,寻找等于key的值
if key > root.val:
root.right = self.deleteNode(root.right,key)
return root
# 删除一个节点会有三种情况:
# 1.待删除的节点左子树为空,让待删除节点的右子树代替它即可
if root.left == None:
new_root = root.right
root.right = None
return new_root
# 2.待删除的节点右子树为空,让待删除节点的左子树代替它即可
if root.right == None:
new_root = root.left
root.left = None
return new_root
# 3. 待删除节点的左右子树都不为空,让待删除节点的前驱结点代替它
node = root.left
# 找到前驱结点
while node.right != None:
node = node.right
# 将前驱节点变为新的根节点
new_root = TreeNode(node.val)
# 前驱节点的左子树进行更新,因为左子树删除了前驱结点
new_root.left = self.removeMax(root.left)
# 新的根节点的右子树不用更新
new_root.right = root.right
# 将删除的根节点的引用去掉
root.left = None
root.right = None
return new_root
def removeMax(self,node):
if node.right == None:
new_root = node.left
node.left = None
return new_root
# 如果右节点不为空,则递归寻找最右节点
node.right = self.removeMax(node.right)