github repo 地址: https://github.com/GoldenaArcher/js_leetcode,Github 的目录 大概 会更新的更勤快一些。
题目地址: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.
这题主要分为以下这么 4 种情况:
结点为空
什么都不需要做,直接返回即可(递归条件中的 base case)
结点为叶结点
直接删除即可
结点只包含左子树或右子树
使用左子树/右子树代替当前结点即可
结点包含左右子树
这个情况是最复杂的,也是解起来比较麻烦的一点,不过这可以利用二叉树的特性:
来解决这道题。
以这张图为例,想要删除的结点为 7,最简单的做法就是将 7 的右子树代替 7:
同时原本的左子树 [5, 4]
挂到 10 的最左结点下:
这个解法利用了上面提到的三个特性,同时也将时间复杂度控制在了 O ( h ) O(h) O(h) 上,但是需要注意的一点就是,在最差情况下,这样的解法可能趋近于 O ( n ) O(n) O(n)——毕竟不是一颗平衡二叉搜索树。
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @param {number} key
* @return {TreeNode}
*/
var deleteNode = function (root, key) {
const dfs = (root) => {
if (!root) return null;
// 如果找到需要删除的结点
if (root.val === key) {
// 只有一棵子树存在,直接返回另外一边即可
if (!root.left) return root.right;
if (!root.right) return root.left;
// 如果存在两棵子树
let curr = root.right;
// 找到右子树的最左结点
while (curr.left) curr = curr.left;
// 将原本的左子树挂载到这里
curr.left = root.left;
return root.right;
}
// search in the right tree
if (key > root.val) root.right = dfs(root.right);
else root.left = dfs(root.left);
return root;
};
return dfs(root);
};