代码随想录算法训练营day22| 235. 二叉搜索树的最近公共祖先 、 701.二叉搜索树中的插入操作 、 450.删除二叉搜索树中的节点

  235. 二叉搜索树的最近公共祖先

题目链接/文章讲解/视频讲解

思路:

在有序树里,如果判断一个节点的左子树里有p,右子树里有q呢?

因为是有序树,所有 如果 中间节点是 q 和 p 的公共祖先,那么 中节点的数组 一定是在 [p, q]区间的。即 中节点 > p && 中节点 < q 或者 中节点 > q && 中节点 < p。

代码实现

 //递归
    var lowestCommonAncestor = function (root, p, q) {
      const travalTree = (cur, p, q) => {
        if (cur === null) return null
        if (cur.val > q.val && cur.val > p.val) {
          let left = travalTree(cur.left, p, q)
          if (left) return left
        }
        if (cur.val < q.val && cur.val < p.val) {
          let right = travalTree(cur.right, p, q)
          if (right) return right
        }
        return cur
      }
      return travalTree(root, p, q)
    };
    //迭代
    var lowestCommonAncestor = function (root, p, q) {
      if (root === null) return null;
      let stack = [root];
      while (stack.length) {
        let cur = stack.pop();
        if (cur.val > p.val && cur.val > q.val) {
          cur = cur.left
          stack.push(cur)
        } else if (cur.val < p.val && cur.val < q.val) {
          cur = cur.right
          stack.push(cur)
        } else {
          return cur

        }
      }

    };

701.二叉搜索树中的插入操作 

题目链接/文章讲解/视频讲解

思路:

代码随想录算法训练营day22| 235. 二叉搜索树的最近公共祖先 、 701.二叉搜索树中的插入操作 、 450.删除二叉搜索树中的节点_第1张图片

代码实现 

function TreeNode (val, left, right) {
      this.val = (val === undefined ? 0 : val)
      this.left = (left === undefined ? null : left)
      this.right = (right === undefined ? null : right)
    }
    //有返回值的递归写法
    var insertIntoBST = function (root, val) {
      const setInOrder = (root, val) => {
        if (root === null) {
          let node = new TreeNode(val);
          return node
        }
        if (root.val > val) {
          root.left = setInOrder(root.left, val);

        } else if (root.val < val) {
          root.right = setInOrder(root.right, val);

        }
        return root
      }
      return setInOrder(root, val);
    };
    //无返回值的递归写法
    var insertIntoBST = (root, val) => {
      let parent = new TreeNode(0);
      const preOrder = (cur, val) => {
        if (cur === null) {
          let node = new TreeNode(val);
          if (parent.val > val) {
            parent.left = node
          } else {
            parent.right = node
          }
          return
        }
        parent = cur
        if (cur.val > val) {
          preOrder(cur.left, val)
        }
        if (cur.val < val) {
          preOrder(cur.right, val)
        }
      }
      if (root === null)
        root = new TreeNode(val)
      preOrder(root, val)
      return root
    }

    //迭代
    var insertIntoBST = (root, val) => {
      if (root === null) {
        root = new TreeNode(val);

      } else {
        let parent = new TreeNode(0)
        let cur = root;
        while (cur) {
          parent = cur
          if (cur.val > val) {
            cur = cur.left
          } else {
            cur = cur.right
          }
        }
        let node = new TreeNode(val);
        if (parent.val > val) {
          parent.left = node
        } else {
          parent.right = node
        }
      }
      return root

    }

 450.删除二叉搜索树中的节点 

题目链接/文章讲解/视频讲解

思路:

  • 第一种情况:没找到删除的节点,遍历到空节点直接返回了
  • 找到删除的节点
    • 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
    • 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
    • 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
    • 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。

代码实现

  var deleteNode = function (root, key) {
      if (!root) return null;
      if (key > root.val) {
        root.right = deleteNode(root.right, key);
        return root;
      } else if (key < root.val) {
        root.left = deleteNode(root.left, key);
        return root;
      } else {
        //叶子节点
        if (!root.left && !root.right) {
          return null
        }
        //有一个孩子节点不存在
        if (root.left && !root.right) {
          return root.left;
        } else if (!root.left && root.right) {
          return root.right
        }
        //左右节点都存在
        const rightNode = root.right;
        //获取最小值节点
        const minNode = getMinNode(rightNode)
        //将待删除节点的值替换为最小值节点值
        root.val = minNode.val;
        //删除最小值节点
        root.right = deleteNode(root.right, minNode.val)
        return root
      }
    };
    function getMinNode (root) {
      while (root.left) {
        root = root.left
      }
      return root
    }
    //迭代
    var deleteNode = (root, key) => {
      const deleteOneNode = target => {
        if (!target) return target
        if (!target.right) return target.left;
        let cur = target.right
        while (cur.left) {
          cur = cur.left
        }
        cur.left = target.left
        return target.right
      }
      if (!root) return root
      let cur = root
      let pre = null
      while (cur) {
        if (cur.val === key) break
        pre = cur
        cur.val > key ? cur = cur.left : cur = cur.right
      }
      if (!pre) {
        return deleteOneNode(cur)
      }
      if (pre.left && pre.left.val === key) {
        pre.left = deleteOneNode(cur)
      }
      if (pre.right && pre.right.val === key) {
        pre.right = deleteOneNode(cur)
      }
      return root
    }

总结

删除二叉搜索树节点的第五种情况不太好理解 继续努力!!

你可能感兴趣的:(算法)