美文网首页论程序员自我修养
五分钟看懂一道中等难度的算法题

五分钟看懂一道中等难度的算法题

作者: 码农小光 | 来源:发表于2020-06-13 00:40 被阅读0次

来自公众号:五分钟学算法
作者P.yh

今天分享的题目来源于 LeetCode 第 450 号问题:删除二叉搜索树中的节点。虽然它的难度是 中等,但实际上很好理解,请往下看!

题目描述

给定一个二叉搜索树的根节点 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

题目解析

在二叉搜索树上删除一个节点,这道题目有一个隐含的条件,就是树上节点的值不重复。

另外题目还要求时间复杂度需要保证 O(h) 这里的 h 表示的是二叉树的高度。

其实这个题目是分成两个步骤的,第一个是找到对应的节点,第二个是删除节点

因为是二叉搜索树,对于树上每个节点来说,其 右子树的节点都要大于其左子树的节点,那么要找对应节点,我们可以从根节点开始,一路比较,大的话就去右边找,小的话就去左边找,这样每次我们都往下,可以保证时间复杂度是 O(h)

当我们找到了要删除的节点,在删除这一步就会有很多的细节,主要是因为我们需要调整余下的结构,以维持二叉搜索树的性质。

针对这个问题,我们可以分情况讨论:

        5
       / \
      3   6
     / \   \
    2   4   7
   /         \
  1           8
  • 情况 1:当删除的节点没有左右子树,比如上图的 4、8、1
    这时直接删除即可,树依旧可以保持二叉搜索树的性质

  • 情况 2:当删除的节点有左子树没有右子树,比如上图的 2
    这时我们只需要将整个左子树移到当前位置即可
    也就是将左子树的根节点放到删除节点的位置,其余不变

  • 情况 3:当删除的节点没有左子树有右子树,比如上图的 6、7
    这时我们只需要将整个右子树移到当前位置即可
    也就是将右子树的根节点放到删除节点的位置,其余不变

  • 情况 4:当删除的节点既有左子树又有右子树,比如上图的 5、3
    这时就有两种方法供选择:
    去到左子树中,找到值最大节点,将右子树全部移到这个节点下
    去到右子树中,找到值最小节点,将左子树全部移到这个节点下

通过上面的讨论分析,我们有了大致的思路。在实现方面,我们可以借助递归来巧妙地达到删除对应节点的目的。

图片描述

image image image image image image image image image image

参考代码

//五分钟学算法
public TreeNode deleteNode(TreeNode root, int key) {
    if (root == null) {
        return null;
    }

    // 当前遍历到的节点大于要找的节点,去左边继续找
    if (root.val > key) {
        root.left = deleteNode(root.left, key);
    }
    // 当前遍历到的节点小于要找的节点,去右边继续找
    else if (root.val < key) {
        root.right = deleteNode(root.right, key);
    } 
    // 找到要删除的节点,进行删除操作
    else {
        // 情况 1 & 2
        if (root.right == null) {
            return root.left;
        } 

        // 情况 3
        if (root.left == null) {
            return root.right;
        }

        // 去到删除节点的右子树,找到值最小的节点
        TreeNode rightSmallest = root.right;
        while (rightSmallest.left != null) {
            rightSmallest = rightSmallest.left;
        }

        // 将删除节点的左子树全部移到这个节点下
        rightSmallest.left = root.left;

        // 返回右子树的根节点,放到当前删除节点的位置
        return root.right;
    }

    return root;
}

相关文章

  • 五分钟看懂一道中等难度的算法题

    来自公众号:五分钟学算法作者P.yh 今天分享的题目来源于 LeetCode 第 450 号问题:删除二叉搜索树中...

  • LeetCode:最长回文子串

    About 我感觉这道题应该是比较经典的题了,甚至有专门解此题的算法,虽然这是一道中等难度的题,但是该题却困扰了我...

  • LeetCode 力扣 47. 全排列 II

    题目描述(中等难度) 和上一道题类似,不同之处就是给定的数字中会有重复的,这样的话用之前的算法会产出重复的序列。例...

  • 算法挑战100天 - one (easy)

    一天一道算法题,按类别划分要求:简单,中等难度要自己写一版,然后再跟最优解对比,说出差异点;困难难度,无计可施时可...

  • LeetCode-15 三数之和

    题目:15. 三数之和 难度:中等 分类:数组 解决方案:双指针 今天我们学习第15题三数之和,这是一道中等题。像...

  • LeetCode-18 四数之和

    题目:18. 四数之和 难度:中等 分类:数组 解决方案:双指针 今天我们学习第18题四数之和,这是一道中等题。像...

  • 寻找二叉树最底层的最左元素

    题目说明 这是leetcode上面的一道中等算法题:https://leetcode.com/problems/f...

  • LeetCode-22 括号生成

    题目:22. 括号生成 难度:中等 分类:字符串 解决方案:链表的遍历 今天我们学习第22题括号生成,这是一道中等...

  • LeetCode-79 单词搜索

    题目:79. 单词搜索 难度:中等 分类:数组 解决方案:DFS、回溯算法 今天我们学习第79题单词搜索,这个题目...

  • LeetCode 力扣 60. 第k个排列

    题目描述(中等难度) 又是一道全排列的题,之前在31题,46题,也讨论过全排列问题的一些解法。这道题的话,是给一个...

网友评论

    本文标题:五分钟看懂一道中等难度的算法题

    本文链接:https://www.haomeiwen.com/subject/uwbptktx.html