【陪伴式刷题】Day 20|二叉树|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:

  1. Search for a node to remove.
  2. If the node is found, delete the node.

Example 1:

Input: root = [5,3,6,2,4,null,7], key = 3 Output: [5,4,6,2,null,null,7] Explanation: Given key to delete is 3. So we find the node with value 3 and delete it. One valid answer is [5,4,6,2,null,null,7], shown in the above BST. Please notice that another valid answer is [5,2,6,null,4,null,7] and it's also accepted.

Example 2:

Input: root = [5,3,6,2,4,null,7], key = 0 Output: [5,3,6,2,4,null,7] Explanation: The tree does not contain a node with value = 0.

Example 3:

Input: root = [], key = 0 Output: []

Constraints:

  • The number of nodes in the tree is in the range [0, 10^4].
  • -10^5 <= Node.val <= 10^5
  • Each node has a unique value.
  • root is a valid binary search tree.
  • -10^5 <= key <= 10^5.

英文版地址

leetcode.com/problems/de...

中文版描述

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

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

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

示例 1:

输入: 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]。

示例 2:

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

示例 3:

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

提示:

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

中文版地址

leetcode.cn/problems/de...

解题方法

递归法

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
         if (root == null) {
            return null;
        }
        if (root.val == key) {
            if (root.left == null && root.right != null) {
                return root.right;
            }else if (root.left != null && root.right == null) {
                return root.left;
            }else if (root.left == null && root.right == null) {
                return null;
            }else {
                TreeNode right = root.right;
                while (right.left != null) {
                    right = right.left;
                }
                right.left = root.left;
                return root.right;
            }
        }
        if (root.val > key) {
            root.left = deleteNode(root.left, key);
        }
        if (root.val < key) {
            root.right = deleteNode(root.right, key);
        }
        return root;
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数,每一个节点恰好被遍历一次
  • 空间复杂度:O(n),为递归过程中栈的开销,平均情况下为 O(log⁡n),最坏情况下树呈现链状,为 O(n)

迭代法

迭代法的关键在于保存当前遍历节点的父节点,这样才能删除它

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur != null && cur.val != key) {
            if (cur.val < key) {
                parent = cur;
                cur = cur.right;
            } else {
                parent = cur;
                cur = cur.left;
            }
        }
        if (cur == null) {
            return root;
        } else if (cur.right == null && cur.left == null) {
            cur = null;
        } else if (cur.right != null && cur.left == null) {
            cur = cur.right;
        } else if (cur.right == null && cur.left != null) {
            cur = cur.left;
        } else {
            TreeNode r = cur.right;
            if (r != null) {
                while (r.left != null) {
                    r = r.left;
                }
                r.left = cur.left;
                cur = cur.right;
            }
        }
        if (parent == null) {
            return cur;
        }
        if (parent != null && parent.left != null && parent.left.val == key) {
            parent.left = cur;
        }
        if (parent != null && parent.right != null && parent.right.val == key) {
            parent.right = cur;
        }

        return root;
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数,每一个节点恰好被遍历一次
  • 空间复杂度:O(1)
相关推荐
小白不太白9502 分钟前
设计模式之 模板方法模式
java·设计模式·模板方法模式
Tech Synapse4 分钟前
Java根据前端返回的字段名进行查询数据的方法
java·开发语言·后端
xoxo-Rachel11 分钟前
(超级详细!!!)解决“com.mysql.jdbc.Driver is deprecated”警告:详解与优化
java·数据库·mysql
乌啼霜满天24913 分钟前
JDBC编程---Java
java·开发语言·sql
色空大师25 分钟前
23种设计模式
java·开发语言·设计模式
闲人一枚(学习中)26 分钟前
设计模式-创建型-建造者模式
java·设计模式·建造者模式
2202_7544215443 分钟前
生成MPSOC以及ZYNQ的启动文件BOOT.BIN的小软件
java·linux·开发语言
蓝染-惣右介1 小时前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis
小林想被监督学习1 小时前
idea怎么打开两个窗口,运行两个项目
java·ide·intellij-idea