删
删除搜索二叉树中某个特定的节点
解析:简单版解析
注意,与我原来的思路完全不同,每一个函数都会返回自己当前处理之后的根节点,换句话说,dfs函数返回的是当前节点的左右子树在删除特定节点并与自己合并后的新树的根节点,迭代往回走的时候会一步步重新构造出这个树。唯一的难点就是当当前节点就是要删除的那个节点时该怎么处理的问题。
当前节点就是要删除的那个节点时而且我左右子树都在的时候是最难想的,其实只需要把原来的头节点的右子树上的最小值(最左边那个)的左子树改成原来头节点的左子树即可
def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
if not root:
return root
def dfs(head, k):
if not head:
return
if k<head.val:
head.left = dfs(head.left, k)
if k>head.val:
head.right = dfs(head.right, k)
if k==head.val:
if not head.right:
return head.left
if not head.left:
return head.right
node = head.right
t = head.right
while node.left:
node = node.left
node.left=head.left
head = t
return head
return dfs(root, key)
还有一种方式,当当前节点就是待删除的节点且左右子树都存在时,任命当前这个节点右子树中最小的那个节点为根节点,这个新的根节点的左子树就是原来根节点的左子树,这个新节点的右子树是原来根节点的右子树删除这个新节点之后的右子树(注意要求先求新节点的右子树在求新节点的左子树)
def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
if not root:
return root
def dfs(head, k):
if not head:
return
if k<head.val:
head.left = dfs(head.left, k)
if k>head.val:
head.right = dfs(head.right, k)
if k==head.val:
if not head.right:
return head.left
if not head.left:
return head.right
node = head.right
while node.left:
node = node.left
# node.right必须先定义,因为此时node仍然是属于这棵树的
# 假设while没有执行,node仍是head.right,如果先实行node.left=head.left的话
# 就会使head.right.left = head.left,从而导致dfs时,传入的树的结构与原来的不同!
# 究其原委还是node.left会改变原来树的结构导致dfs时的参数不正确,虽然node.left=head.left本身没有影响
node.right = dfs(head.right, node.val)
node.left = head.left
head = node
return head
return dfs(root, key)