Q:给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。
示例:
root = [5,3,6,2,4,null,7]
key = 3
5
/
3 6
/
2 4 7
给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
5
/
4 6
/
2 7
另一个正确答案是 [5,2,6,null,4,null,7]。
5
/
2 6
4 7
A:
如果 key > root.val,说明要删除的节点在右子树,root.right = deleteNode(root.right, key)。
如果 key < root.val,说明要删除的节点在左子树,root.left = deleteNode(root.left, key)。
如果 key == root.val,则该节点就是我们要删除的节点,则:
如果该节点是叶子节点,则直接删除它:root = null。
如果该节点不是叶子节点且有右节点,则用它的后继节点的值替代 root.val = successor.val,然后删除后继节点。
如果该节点不是叶子节点且只有左节点,则用它的前驱节点的值替代 root.val = predecessor.val,然后删除前驱节点。
返回 root。
1 public TreeNode deleteNode(TreeNode root, int key) { 2 if (root == null) 3 return null; 4 if (key > root.val) { 5 root.right = deleteNode(root.right, key); 6 } else if (key < root.val) { 7 root.left = deleteNode(root.left, key); 8 } else { 9 if (root.left == null && root.right == null) { 10 root = null; 11 } else if (root.left == null) { 12 root.val = rightMin(root); 13 root.right = deleteNode(root.right, root.val); 14 } else { 15 root.val = leftMax(root); 16 root.left = deleteNode(root.left, root.val); 17 } 18 } 19 return root; 20 } 21 22 private int leftMax(TreeNode root) { 23 root = root.left; 24 while (root.right != null) 25 root = root.right; 26 return root.val; 27 } 28 29 private int rightMin(TreeNode root) { 30 root = root.right; 31 while (root.left != null) 32 root = root.left; 33 return root.val; 34 }