Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

删除二叉搜索树中的节点-450 #62

Open
sl1673495 opened this issue Jun 9, 2020 · 0 comments
Open

删除二叉搜索树中的节点-450 #62

sl1673495 opened this issue Jun 9, 2020 · 0 comments
Labels
DFS 深度优先遍历 二叉树 待复习 看题解或者做出来很艰难的,需要回顾。

Comments

@sl1673495
Copy link
Owner

sl1673495 commented Jun 9, 2020

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-node-in-a-bst
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这题我的思路是这样的,先通过递归去找到目标节点的 父节点 parent,和目标节点的位置 posleftright,方便后续删除操作。

  1. 待删除节点没有 left或者 right 子节点的情况下,直接吧 parent[pos] = null 清空即可。
  2. 待删除节点只有 left 或只有 right,那就把 parent[pos] 赋值为存在的那个子节点即可。
  3. 如果 leftright 都在的情况下,比较复杂一些,把待删除节点的左右子节点分别称为 targetLefttargetRight,先找到targetRight的最左子节点,这个子节点一定在右子树中最小,但是在左子树中最大。然后把 parent[pos] 赋值为 targetRight,再把 targetRight的最左下角子节点的 left 赋值成原来的 targetLeft 即可。
let deleteNode = function (root, key) {
  let findNodePos = (node, key) => {
    if (!node) {
      return false
    }
    if (node.left && node.left.val === key) {
      return {
        parent: node,
        pos: "left",
      }
    } else if (node.right && node.right.val === key) {
      return {
        parent: node,
        pos: "right",
      }
    } else {
      return findNodePos(node.left, key) || findNodePos(node.right, key)
    }
  }

  let findLastLeft = (node) => {
    if (!node.left) {
      return node
    }
    return findLastLeft(node.left)
  }

  let virtual = new TreeNode()
  virtual.left = root

  let finded = findNodePos(virtual, key)
  if (finded) {
    let { parent, pos } = finded
    let target = parent[pos]
    let targetLeft = target.left
    let targetRight = target.right

    if (!targetLeft && !targetRight) {
      parent[pos] = null
    } else if (!targetRight) {
      parent[pos] = targetLeft
    } else if (!targetLeft) {
      parent[pos] = targetRight
    } else {
      parent[pos] = targetRight
      let lastLeft = findLastLeft(targetRight)
      lastLeft.left = targetLeft
    }
  }

  return virtual.left
}
@sl1673495 sl1673495 added DFS 深度优先遍历 待复习 看题解或者做出来很艰难的,需要回顾。 二叉树 labels Jun 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DFS 深度优先遍历 二叉树 待复习 看题解或者做出来很艰难的,需要回顾。
Projects
None yet
Development

No branches or pull requests

1 participant