前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >字节面试,HR给了道我做过的题,心中窃喜,但我假装不会,思考了两分钟,先给了非最优解,等面试官提示,再给了最优解,尺度把控可行?

字节面试,HR给了道我做过的题,心中窃喜,但我假装不会,思考了两分钟,先给了非最优解,等面试官提示,再给了最优解,尺度把控可行?

作者头像
五分钟学算法
发布2024-03-18 11:23:30
1120
发布2024-03-18 11:23:30
举报
文章被收录于专栏:五分钟学算法五分钟学算法

大家好,我是吴师兄。

众所周知,人生如戏全靠演技,出门在外,咱们靠的都是一个“人设”,面试就是展示自己人设的一个场景,从面试进门的那个时刻起,我们就开始了职场“表演”,有的人想把自己塑造成技术高手,有的人想打造工作干练的形象。

而有的人却选择了反向操作

一位参加字节面试的同学面对熟悉的问题时,不直接给出答案,而是展现出层层思考、逐步优化的过程,这个操作确实容易让面试官参与进来进而加深其印象。

演技很好,可惜却被面试官识破

所以如果字节面试过程中如果遇到下方这种简单且熟悉的题目,最好秒解

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

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

1、首先找到需要删除的节点;

2、如果找到了,删除它。

二叉搜索树(BST)是一种特殊的二叉树,对于任意节点,其左子树中的所有节点的值都小于该节点的值,右子树中的所有节点的值都大于该节点的值。

这个性质使得二叉搜索树在查找、插入和删除操作上有很好的性能

当需要在二叉搜索树中删除一个节点时,我们需要考虑以下几种情况:

  1. 节点不存在:如果树为空,或者没有找到要删除的节点,什么也不做,直接返回 null 或原节点。
  2. 节点为叶子节点或只有一个子节点:这种情况比较简单。
    • 如果要删除的节点没有左子树,我们可以直接用其右子树替代该节点。
    • 如果没有右子树,则用左子树替代。
    • 这实质上是将要删除节点的父节点直接连接到要删除节点的子节点上。
  3. 节点既有左子树又有右子树:这种情况稍微复杂一点。
    • 首先,找到要删除节点右子树中的最小节点(或左子树中的最大节点),这个节点将替代要删除的节点。
    • 然后,将要删除节点的值替换为找到的最小(或最大)节点的值。
    • 最后,删除原右子树中的最小节点(或左子树中的最大节点),因为它已经被移动到了要删除的节点的位置。

deleteNode(TreeNode root, int key) 方法是主要的逻辑实现,它递归地在二叉树中查找并删除指定值的节点。

如果找到了需要删除的节点 root.val == key,根据上面的情况进行处理:

  • 如果节点的左子树或右子树为空,直接用存在的子树替换当前节点。
  • 如果节点既有左子树又有右子树,则需要找到右子树的最小节点(通过 findMinNode(TreeNode node) 方法),用这个最小节点的值替换当前节点的值,然后删除右子树中的这个最小节点。
  • 如果当前节点的值小于需要删除的值,则在右子树中继续查找;如果大于,则在左子树中查找。
  • findMinNode(TreeNode node) 方法用于找到以 node 为根的子树中的最小值节点。由于二叉搜索树的性质,这个最小值节点肯定在最左边,因此通过不断访问左子节点直到 null 即可找到最小值节点。

通过这种方式,可以有效地在二叉搜索树中删除任意一个节点,同时保持二叉搜索树的性质不变。

代码如下:

代码语言:javascript
复制
// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
// 删除二叉搜索树中的节点( LeetCode 450 ):https://leetcode-cn.com/problems/delete-node-in-a-bst/
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {

        // 1、如果 root 为空,那么直接返回空
        if (root == null) return null;

        // 2、如果 root 的节点值等于需要删除的值,那么需要根据以下几种情况进行处理
        if (root.val == key) {
     
            // 情况 1:当前节点的左子树为空,那么当前节点 root 由 root 的右子树占位就行
            // 比如 key 为 7
            //       6
            //     /   \
            //    2     7
            //           \
            //            8
            // 直接将以 8 作为根节点的二叉树挪到 7 的位置
            //       6
            //     /   \
            //    2     8
            if (root.left == null) return root.right;

            // 情况 2:当前节点的右子树为空,那么当前节点 root 由 root 的左子树占位就行
            // 比如 key 为 2
            //       6
            //     /   \
            //    2     7
            //   /        
            //  1          
            // 直接将以 1 作为根节点的二叉树挪到 2 的位置
            //       6
            //     /   \
            //    1     7
            if (root.right == null) return root.left;

            // 情况 3:被删除节点既有左子树,又有右子树
            // 比如 key 为 2
            //          5
            //       /     \
            //      2       6
            //    /   \       \
            //   1     4       7
            //        /
            //       3
            // 需要找到右子树最小的值,或者左子树中最大的值
            // 这里我们去找右子树最小的值,为 3
            TreeNode minNodeOfRight = findMinNode(root.right);

            // 找到右子树最小的值之后,修改当前节点 root 的值为右子树最小的值
            root.val = minNodeOfRight.val;
            
            // 同时,记得删除掉 root 的右子树最小的值之
            // 删除操作就是以 root 作为根节点,key 为右子树最小的值进行删除
            root.right = deleteNode(root.right, minNodeOfRight.val);
          
          // 3、如果 root 的节点值小于需要删除的值,那么就在 root 的右子树中去查找
        } else if (root.val < key) {
            // 在 root 的右子树中去查找并删除 key 
            root.right = deleteNode(root.right, key);

          // 4、如果 root 的节点值大于需要删除的值,那么就在 root 的左子树中去查找
        } else if (root.val > key) {
            // 在 root 的左子树中去查找并删除 key 
            root.left = deleteNode(root.left, key);
        }

        // 最后返回需要已经删除了 key 的二叉树的根节点
        return root;
    }

    // 通过 findMinNode ,可以找到二叉搜索树中最小的元素
    private TreeNode findMinNode(TreeNode node) {

        // 由于二叉搜索树,左子树所有元素的值都小于根节点的值
        // 所以可以不断的查找,直到为叶子节点,那么就找到了
        while (node.left != null) {
            // 不断的去查找当前节点的左子树
            node = node.left;
        }

        // 返回当前二叉搜索树中最小的元素
        return node;
    }
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 五分钟学算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档