代码随想录算法训练营|Day 20
Day 20
第六章 二叉树part07
235. 二叉搜索树的最近公共祖先
相对于 二叉树的最近公共祖先 本题就简单一些了,因为 可以利用二叉搜索树的特性。
题目链接/文章讲解:https://programmercarl.com/0235.二叉搜索树的最近公共祖先.html
视频讲解:https://www.bilibili.com/video/BV1Zt4y1F7ww
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if min(p.val, q.val) < root.val < max(p.val,q.val) or root.val == min(p.val,q.val) or root.val == max(p.val,q.val):
return root
else:
return self.lowestCommonAncestor(root.left if max(p.val,q.val) < root.val else root.right, p, q)
从上向下去递归遍历,第一次遇到 cur节点是数值在[q, p]区间中,那么cur就是 q和p的最近公共祖先。
思路:对于BST, 若p/q均大于cur.val,那么向右子树搜索;若p/q均小于cur.val,那么向左子树搜索
若cur.val在p/q之间,则cur本身是最近公共祖先
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if p.val > root.val and q.val > root.val:
right = self.lowestCommonAncestor(root.right, p, q)
elif p.val < root.val and q.val < root.val:
left = self.lowestCommonAncestor(root.left, p, q)
else:
return root
迭代法
class Solution:
def lowestCommonAncestor(self, root, p, q):
while root:
if root.val > p.val and root.val > q.val:
root = root.left
elif root.val < p.val and root.val < q.val:
root = root.right
else:
return root
return None
701.二叉搜索树中的插入操作
本题比想象中的简单,大家可以先自己想一想应该怎么做,然后看视频讲解,就发现 本题为什么比较简单了。
题目链接/文章讲解:https://programmercarl.com/0701.二叉搜索树中的插入操作.html
视频讲解:https://www.bilibili.com/video/BV1Et4y1c78Y
递归法
class Solution:
def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if not root:
return TreeNode(val)
if root.val > val:
root.left = self.insertIntoBST(root.left, val)
elif root.val < val:
root.right = self.insertIntoBST(root.right, val)
return root
迭代法
class Solution:
def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
if not root: # 如果根节点为空,创建新节点作为根节点并返回
return TreeNode(val)
cur = root
while cur:
if val < cur.val:
if not cur.left: # 如果此时父节点的左子树为空
cur.left = TreeNode(val) # 将新节点连接到父节点的左子树
return root
else:
cur = cur.left
elif val > cur.val:
if not cur.right: # 如果此时父节点的左子树为空
cur.right = TreeNode(val) # 将新节点连接到父节点的右子树
return root
else:
cur = cur.right
450.删除二叉搜索树中的节点
相对于 插入操作,本题就有难度了,涉及到改树的结构
题目链接/文章讲解:https://programmercarl.com/0450.删除二叉搜索树中的节点.html
视频讲解:https://www.bilibili.com/video/BV1tP41177us
下面这种是取代的方法
当要删除的节点有左右孩子,用左子树的最大值or右子树的最小值去取代节点本身,再删除我们选择的那个最大值or最小值
class Solution:
def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
if not root:
return root
if root.val > key:
root.left = self.deleteNode(root.left,key)
elif root.val < key:
root.right = self.deleteNode(root.right, key)
else:
if not root.right:
return root.left
elif not root.left:
return root.right
else:
minNode = self.findMin(root.right)
root.val = minNode.val
root.right = self.deleteNode(root.right, minNode.val)
return root
def findMin(self, root):
curr = root
while curr.left:
curr = curr.left
return curr
情况:
-
没找到需要删除的节点
-
找到了节点
- 删的点是叶子节点
- 删的点非叶子节点
- 左为空,右不为空 ->父节点指向右孩子
- 左不为空,右为空 ->父节点指向左孩子
- 左右都不为空 -> 左子树成为右子树最小的左孩子,父节点指向右子树
递归法
class Solution:
def deleteNode(self, root, key):
if root is None:
return root
if root.val == key:
if root.left is None and root.right is None:
return None
elif root.left is None:
return root.right
elif root.right is None:
return root.left
else:
cur = root.right
#找到右子树的最小值
while cur.left is not None:
cur = cur.left
#把左子树接到右子树上
cur.left = root.left
#返回修正好的树
#修正好的树直接没有值等于key的根节点了
return root.right
if root.val > key:
root.left = self.deleteNode(root.left,key)
if root.val < key:
root.right = self.deleteNode(root.right,key)
return root
递归法
class Solution:
def deleteNode(self, root, key):
if root is None: # 如果根节点为空,直接返回
return root
if root.val == key: # 找到要删除的节点
#包含的情况:
#1. 左右子树都为空
#2. 左子树不为空,右为空
if root.right is None: # 如果右子树为空,直接返回左子树作为新的根节点
return root.left
#3.左为空,右不空
#4.左右都不空
cur = root.right
while cur.left: # 找到右子树中的最左节点
cur = cur.left
root.val, cur.val = cur.val, root.val # 将要删除的节点值与最左节点值交换
root.left = self.deleteNode(root.left, key) # 在左子树中递归删除目标节点
root.right = self.deleteNode(root.right, key) # 在右子树中递归删除目标节点
return root
不想看迭代法了但是存一个
迭代法
class Solution:
def deleteOneNode(self, target: TreeNode) -> TreeNode:
"""
将目标节点(删除节点)的左子树放到目标节点的右子树的最左面节点的左孩子位置上
并返回目标节点右孩子为新的根节点
是动画里模拟的过程
"""
if target is None:
return target
if target.right is None:
return target.left
cur = target.right
while cur.left:
cur = cur.left
cur.left = target.left
return target.right
def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
if root is None:
return root
cur = root
pre = None # 记录cur的父节点,用来删除cur
while cur:
if cur.val == key:
break
pre = cur
if cur.val > key:
cur = cur.left
else:
cur = cur.right
if pre is None: # 如果搜索树只有头结点
return self.deleteOneNode(cur)
# pre 要知道是删左孩子还是右孩子
if pre.left and pre.left.val == key:
pre.left = self.deleteOneNode(cur)
if pre.right and pre.right.val == key:
pre.right = self.deleteOneNode(cur)
return root

浙公网安备 33010602011771号