这一节再解析两道题,略有难度的。
450. Delete Node in a BST
Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.
Basically, the deletion can be divided into two stages:
- Search for a node to remove.
- If the node is found, delete the node.
Note: Time complexity should be O(height of tree).
题目解析
一道标准的基本功题目,前面对于AVL的结点的删除,没有详细解析。我们且看普通的BST的结点删除。
第一步,找到待删的结点;第二步,根据待删结点左右子树的情况,进行操作。
注意的是,当删除结点是根结点时,都要进行特殊处理,并返回新的根结点;不是的话,要记录待删结点的父节点(所以上一节的问题中,树的字段中保留了父结点,便于处理问题),并在删除结点后,将新的结点与这个父结点连接,返回值还是原来的根节点。
当删除结点既有左又有右子树时,确实问题比较复杂:1. 查找前继结点 2. 交接工作(左右子树交接) 3. 与删除结点的父亲相认
class Solution:
def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
p = root
par = None # 待删结点的父结点
flag = 0 # par与待删结点的关系
is_root = False # 待删结点是否是根结点
while p and key != p.val:
par = p
if key < p.val:
flag = 0
p = p.left
else:
flag = 1
p = p.right
if not p:
return root
if p == root:
is_root = True
if not p.left and not p.right:
if is_root:
return None
if flag:
par.right = None
else:
par.left = None
elif not p.left or not p.right:
ch = p.left if p.left else p.right
if is_root:
return ch
if flag:
par.right = ch
else:
par.left = ch
else:
# 既有左子树也有右子树的
q = p.left
pre = p
while q.right:
pre = q
q = q.right # p左子树右下结点
if pre != p:
pre.right = q.left
q.left = p.left
q.right = p.right
if is_root:
return q
if flag:
par.right = q
else:
par.left = q
return root
99. Recover Binary Search Tree
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
题目解析:
该题hard难度,但是实际上并没有太难的代码逻辑,关键是解题思路,BST中序遍历序列是递增,但是这两个错误的结点在中序遍历序列中一定是破坏了递增规律的。该方法跑起来蛮快的,就是一遍中序遍历,目标是找到两个结点对象:第一个是比后一个结点的值大的结点,即fir_node,第二个是比前一个结点的值小的结点,即sec_node。注意fir_node 的后一个结点是一定满足sec_node的,这个结点也真的可能是sec_node。最后我们把两个结点的值交换一下即可。该方法击败92%。
class Solution:
def recoverTree(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
stack = []
pre_node = None
fir_node = None
sec_node = None
while root or stack:
while root:
stack.append(root)
root = root.left
root = stack.pop()
if not fir_node:
if pre_node:
if root.val < pre_node.val:
fir_node = pre_node
if fir_node:
if root.val < pre_node.val:
sec_node = root
pre_node = root
root = root.right
fir_node.val, sec_node.val = sec_node.val, fir_node.val
BST的内容先到这里,消化吸收一下。
下面继续是精彩的二叉树相关内容[捂脸]。。。