[Leetcode 60 days with brush] day22 binary tree - 235. The nearest common ancestor of the binary search tree, 701. The insertion operation in the binary search tree, 450. Delete the node in the binary search tree

 


  topic:

235. Nearest Common Ancestor of Binary Search Tree

Given a binary search tree, find the nearest common ancestor of two specified nodes in the tree.

The definition of the nearest common ancestor in Baidu Encyclopedia is: "For two nodes p and q of a rooted tree T, the nearest common ancestor is expressed as a node x, satisfying that x is the ancestor of p and q and the depth of x is as large as possible ( A node can also be its own ancestor )."

For example, given the following binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]

Example 1:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
 Output: 6 
 Explanation: The nearest common ancestor of node 2 and node is8 6。

Example 2:

Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
 Output: 2
 Explanation: The nearest common ancestor of node 2and node is , because By definition the nearest common ancestor node can be the node itself.42

illustrate:

  • All node values ​​are unique.
  • p and q are different nodes and both exist in a given binary search tree.

 Thinking process and knowledge points: 

In an ordered tree, if it is judged that there is p in the left subtree of a node and q in the right subtree?

Because it is an ordered tree, if the intermediate node is the common ancestor of q and p, then the array of intermediate nodes must be in the interval [p, q]. That is, midnode > p && midnode < q or midnode > q && midnode < p.

When traversing the binary search tree, it is to look for the interval [p->val, q->val] (note that this is left-closed and closed)

Then if cur->val is greater than p->val, and cur->val is greater than q->val, then it should traverse to the left (indicating that the target interval is on the left subtree).


 answer:

private:
    TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q) {
        if (cur == NULL) return cur;
                                                        // 中
        if (cur->val > p->val && cur->val > q->val) {   // 左
            TreeNode* left = traversal(cur->left, p, q);
            if (left != NULL) {
                return left;
            }
        }

        if (cur->val < p->val && cur->val < q->val) {   // 右
            TreeNode* right = traversal(cur->right, p, q);
            if (right != NULL) {
                return right;
            }
        }
        return cur;
    }
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        return traversal(root, p, q);
    }
};

  topic:

701. Insertion in a Binary Search Tree

Given a binary search tree (BST) root node  root and a value to insert into the tree  value , insert a value into the binary search tree. Returns the root node of the binary search tree after insertion. The input data  guarantees  that the new value is different from any node value in the original binary search tree.

Note that there may be more than one efficient way of inserting, as long as the tree remains a binary search tree after inserting. You can return  any valid result  .

Example 1:

Input: root = [4,2,7,1,3], val = 5
 Output: [4,2,7,1,3,5]
 Explanation: Another tree that can meet the requirements of the topic is:

Example 2:

Input: root = [40,20,60,10,30,50,70], val = 25
 Output: [40,20,60,10,30,50,70,null,null,25]

Example 3:

Input: root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
 Output: [4,2,7,1,3,5]

hint:

  • The number of nodes in the tree will be  [0, 104]in the range of .
  • -108 <= Node.val <= 108
  • All values  Node.val ​​are  unique  .
  • -108 <= val <= 108
  • guaranteed val  not to exist in the original BST.

 answer:

class Solution {
private:
    TreeNode* parent;
    void traversal(TreeNode* cur, int val) {
        if (cur == NULL) {
            TreeNode* node = new TreeNode(val);
            if (val > parent->val) parent->right = node;
            else parent->left = node;
            return;
        }
        parent = cur;
        if (cur->val > val) traversal(cur->left, val);
        if (cur->val < val) traversal(cur->right, val);
        return;
    }

public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        parent = new TreeNode(0);
        if (root == NULL) {
            root = new TreeNode(val);
        }
        traversal(root, val);
        return root;
    }
};

  topic:

450. Delete a Node in a Binary Search Tree

Given a root node root  of a binary search tree  and a value  key , delete the node corresponding to the key  in the binary search tree  , and ensure that the nature of the binary search tree remains unchanged. Returns a reference to the (possibly updated) root node of the binary search tree.

In general, deleting a node can be divided into two steps:

  1. First find the node that needs to be deleted;
  2. If found, delete it.

Example 1:

Input: root = [5,3,6,2,4,null,7], key = 3
 Output: [5,4,6,2,null,null,7]
 Explanation: Given the node value that needs to be deleted is 3, so we first find the node 3 and delete it. 
A correct answer is [5,4,6,2,null,null,7] as shown in the figure below. 
Another correct answer is [5,2,6,null,4,null,7].


Example 2:

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

Example 3:

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

hint:

  • The range of the number of nodes  [0, 104].
  • -105 <= Node.val <= 105
  • Node value is unique
  • root is a valid binary search tree
  • -105 <= key <= 105

Thinking process and knowledge points: 

Here we will clarify all the situations encountered in deleting nodes in the binary search tree.

There are five situations:

  • The first case: the deleted node is not found, and the empty node is traversed and returned directly
  • find the deleted node
    • The second case: both left and right children are empty (leaf nodes), delete the node directly, and return NULL as the root node
    • The third case: the left child of the deleted node is empty, the right child is not empty, the node is deleted, the right child is filled, and the right child is returned as the root node
    • The fourth case: the right child of the deleted node is empty, the left child is not empty, the node is deleted, the left child is filled, and the left child is returned as the root node
    • Case 5: both the left and right child nodes are not empty, then put the left child of the left subtree of the deleted node on the left child of the leftmost node of the right subtree of the deleted node, and return the right child of the deleted node for the new root node.

 answer:

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == nullptr) return root; // 第一种情况:没找到删除的节点,遍历到空节点直接返回了
        if (root->val == key) {
            // 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
            if (root->left == nullptr && root->right == nullptr) {
                ///! 内存释放
                delete root;
                return nullptr;
            }
            // 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
            else if (root->left == nullptr) {
                auto retNode = root->right;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
            else if (root->right == nullptr) {
                auto retNode = root->left;
                ///! 内存释放
                delete root;
                return retNode;
            }
            // 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
            // 并返回删除节点右孩子为新的根节点。
            else {
                TreeNode* cur = root->right; // 找右子树最左面的节点
                while(cur->left != nullptr) {
                    cur = cur->left;
                }
                cur->left = root->left; // 把要删除的节点(root)左子树放在cur的左孩子的位置
                TreeNode* tmp = root;   // 把root节点保存一下,下面来删除
                root = root->right;     // 返回旧root的右孩子作为新root
                delete tmp;             // 释放节点内存(这里不写也可以,但C++最好手动释放一下吧)
                return root;
            }
        }
        if (root->val > key) root->left = deleteNode(root->left, key);
        if (root->val < key) root->right = deleteNode(root->right, key);
        return root;
    }
};

Welcome to like, bookmark, comment, your encouragement is the biggest motivation for my creation! (๑╹◡╹)ノ"""

Copyright statement: This article is an original article of CSDN blogger "Dumengjiu", which follows the CC 4.0 BY-SA copyright agreement. For reprinting, please attach the original source link and this statement.
Original link: Dumengjiu's blog_CSDN blog-csdn domain blogger

Guess you like

Origin blog.csdn.net/weixin_53310927/article/details/131355800