235. 二叉搜索树的最近公共祖先
题目:
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
思路:
二叉搜索树的特点是有顺序,所以直接看当前的结点和p,q的大小。一共三种情况,比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 travesal(self,cur,p,q): # 创建递归函数
# 终止条件
if cur is None or cur==p or cur==q:
return cur
# 左
if cur.val>p.val and cur.val>q.val:
left=self.travesal(cur.left,p,q)
if left is not None:
return left
# 右
if cur.val<p.val and cur.val<q.val:
right=self.travesal(cur.right,p,q)
if right is not None:
return right
return cur
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
return self.travesal(root,p,q) # 调用递归函数
701.二叉搜索树中的插入操作
题目:
给定二叉搜索树(BST)的根节点 root
和要插入树中的值 value
,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
思路:
递归:
感觉不是很理解,大概的核心思想是,找一个叶子结点,只要满足插入后还是一个二叉树,就可以。重要的引入了parent,node,cur这些辅助的结点,需要再体会。
代码:
# 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 __init__(self):
self.parent=None # 父结点
# 创建递归函数
def traversal(self,cur,val):
if cur is None: # 2 终止条件
node=TreeNode(val) # 设置一个新节点,它的值为val 到时候插入新节点可以直接用
if val>self.parent.val:
self.parent.right=node
else:
self.parent.left=node
return
self.parent=cur # 把cur的值赋值给父节点
if cur.val>val:
self.traversal(cur.left,val)
if cur.val<val:
self.traversal(cur.right,val)
def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
self.parent=TreeNode(0)
# 如果根节点是空的,直接返回包含给出的参数val的新节点
if root is None:
return TreeNode(val)
# 调用递归函数
self.traversal(root,val)
return root
450.删除二叉搜索树中的节点
题目:
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
- 首先找到需要删除的节点;
- 如果找到了,删除它。
思路:
找到这个key,需要遍历;
重要的是删除之后,需要重新排列二叉树的结点,使得其还是二叉搜索树。
分析五种情况;不是完全理解,但是我觉得这个做法比较新颖,就是之前我没有做过的。大概逻辑知道了。
代码:
# 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: Optional[TreeNode], key: int) -> Optional[TreeNode]:
if root is None: # 1 没找到key
return root
if root.val == key: # 找到key了
if root.left is None and root.right is None: # 2 左右都空,是叶子节点
return None
elif root.left is not None and root.right is None: # 3 左不空右空
return root.left
elif root.left is None and root.right is not None: # 4 左空右不空
return root.right
else: # 5 左不空右不空
cur = root.right # 右子树继承
while cur.left is not None: # 只要左边的结点不为空,一直补到它的左子树
cur = cur.left
cur.left = root.left # 将结点右子树中最小值复制到它的位子上
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