「LeetCode」450-删除二叉搜索树中的节点

585 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

一.题目:

450. 删除二叉搜索树中的节点 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。 示例 1:

image.png

输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。

![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/effcff6fe8394e66a4e1382a55933515~tplv-k3u1fbpfcp-watermark.image?)

示例 2:

输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点

示例 3:

输入: root = [], key = 0
输出: []

提示:

  • 节点数的范围 [0, 104].
  • -105 <= Node.val <= 105
  • 节点值唯一
  • root 是合法的二叉搜索树
  • -105 <= key <= 105

二、思路分析:

根据题意来解决问题,题目要求我们能够删除对应key值的节点且不破坏二叉搜索树的结构,所以基本的步骤是:

  • 根据题目信息首先需要找到这个节点
  • 找到这个节点后我们需要考虑删除的每个情况:
  1. 找到的节点正好是叶子节点的时候,我们就不需要考虑其他情况,直接删除节点完成任务。
  2. 第二种情况,如果是只有一个子树的情况下,我们就直接返回这个单独的子树即可完成删除目标节点的操作。
  3. 第三种情况最复杂,目标节点左右子树,我们应该选择左子树的最大值或者右子树的最小值来替代这个节点,这样才不会破坏二叉搜素树的结构,这里我选择的是右子树的最小节点进行替换,因为这样符合我们的眼睛喜欢从左往右看的习惯=。=

三、代码:

/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     val: number
 *     left: TreeNode | null
 *     right: TreeNode | null
 *     constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.left = (left===undefined ? null : left)
 *         this.right = (right===undefined ? null : right)
 *     }
 * }
 */

function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
    if(!root) return null;
    function getMin(node: TreeNode): TreeNode{
        while(node.left !== null) node = node.left;
        return node;
    }
    if(root.val === key){
        // 情况1 找到的节点是叶子节点
        if(!root.left && !root.right) return null;
        // 情况2
        if(root.left === null) return root.right; 
        if(root.right === null) return root.left; 
        // 情况3 用右子树最小节点替换目标节点
        const minNode: TreeNode = getMin(root.right);
        root.right = deleteNode(root.right, minNode.val);
        minNode.left = root.left;
        minNode.right = root.right;
        root = minNode;
    }else if(root.val > key){
        root.left = deleteNode(root.left, key);
    }else if(root.val < key){
        root.right = deleteNode(root.right,key);
    }
    return root;
};

四、总结:

这道题目的整体思路也不是特别难,需要的是你的考虑问题的全面性,针对这道题目我们要想到删除节点有三种情况,如果能够想到的话那么这道题目就不是很难。所以一般的题目难的是思维!