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

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

时间:2022-12-23 21:57:37浏览次数:66  
标签:right TreeNode val root 二叉 搜索 NULL 树中 left

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

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

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

首先题目要求:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

这说明我们可以通过数值唯一确定每个节点,并且排除了异常输入的考虑。

①二叉树常规做法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        // 递归终止条件
        // if (root == NULL) return NULL;
        // if (root == p || root == q) return root;
        if (root == NULL || root == p || root == q) return root;

        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        if (left != NULL && right != NULL) return root;
        // 如果只有一边有返回节点
        else if (left != NULL && right == NULL) return left;
        else return right;
    }
};

②利用二叉搜索树的特性

由于BST的特性,公共祖先的数值肯定在[p, q]范围内:这意味着,当遍历到节点数值在[p, q]范围内时,就可以确定其为公共祖先。

目前的问题是首次遇见的公共祖先节点是否为「最近公共祖先节点」?

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

图中能看出,使用从上到下的遍历方法获得的首个节点即为「最近公共祖先」。因此不需要遍历整棵树,只需要遍历分支,在遇到合适的节点后立即返回即可。代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == NULL) return NULL;
        // 规范给定节点的数值大小
        if (p->val > q->val) swap(p, q);
        if (root->val >= p->val && root->val <= q->val) return root;
        if (root->val < p->val) return lowestCommonAncestor(root->right, p, q);
        if (root->val > p->val) return lowestCommonAncestor(root->left, p, q);
        return NULL;
    }
};

因为p、q节点顺序未知,所以需要在判断前使用swap函数进行规范。

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

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

需要明确的是,不需要调整二叉树的结构,直接在叶子节点进行添加即可。

①判断当前节点的孩子节点

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == NULL) {
            TreeNode* node = new TreeNode(val);
            return node;
        }
        else
            return traversal(root, val); 
    }

    TreeNode* traversal(TreeNode* root, int val) {
        if (root == NULL) return NULL;
        if (root->val > val) {
            if (traversal(root->left, val) == NULL) {
                TreeNode* node = new TreeNode(val);
                root->left = node;
                return root;
            }
        } 
        else  {
            if (traversal(root->right, val) == NULL) {
                TreeNode* node = new TreeNode(val);
                root->right = node;
                return root;
            }
        }
        return root;
    }
};

②直接判断当前节点

直接判断当前节点,只要节点为空,即找到插入新节点的位置。

为了保证第一次终止的空节点为目标位置,需要利用二叉搜索树的性质,来寻找合适的搜索路径。又因为题目说明所有值 Node.val 是 独一无二的保证 val 在原始BST中不存在,所以不需要考虑节点相等的情况,代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == NULL) {
            TreeNode* node = new TreeNode(val);
            return node;
        }
        if (root->val > val)root->left = insertIntoBST(root->left, val);
        else root->right = insertIntoBST(root->right, val);
        return root;
    }
};

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

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

需要分情况进行讨论:

有以下五种情况:

  • 第一种情况:没找到删除的节点,遍历到空节点直接返回了

  • 找到删除的节点

    • 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点

    • 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点

    • 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点

    • 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。

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

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == NULL) return NULL;
        if (root->val == key) {
            // 分情况讨论
            if (root->left == NULL && root->right == NULL) {
                delete root;
                return NULL;
            }
            else if (root->left != NULL && root->right == NULL) {
                TreeNode* tmp = root->left;
                delete root;
                return tmp;
            }
            else if (root->left == NULL && root->right != NULL) {
                TreeNode* tmp = root->right;
                delete root;
                return tmp;
            }
            else {
                TreeNode* cur = root->right;
                while (cur->left != NULL) cur = cur->left;
                cur->left = root->left;
                TreeNode* right = root->right;
                delete root;
                return right;
            }
        }
        root->left = deleteNode(root->left, key);
        root->right = deleteNode(root->right, key);
        return root;
    }
};

根据二叉搜索树的特性,在遍历路径的时候可以剪枝一下,注意这里也需要整棵树遍历:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (root == NULL) return NULL;
        if (root->val == key) {
            // 分情况讨论
            if (root->left == NULL && root->right == NULL) {
                delete root;
                return NULL;
            }
            else if (root->left != NULL && root->right == NULL) {
                TreeNode* tmp = root->left;
                delete root;
                return tmp;
            }
            else if (root->left == NULL && root->right != NULL) {
                TreeNode* tmp = root->right;
                delete root;
                return tmp;
            }
            else {
                TreeNode* cur = root->right;
                while (cur->left != NULL) cur = cur->left;
                cur->left = root->left;
                TreeNode* right = root->right;
                delete root;
                return right;
            }
        }
        if (root->val > key) root->left = deleteNode(root->left, key);
        else root->right = deleteNode(root->right, key);
        return root;
    }
};

标签:right,TreeNode,val,root,二叉,搜索,NULL,树中,left
From: https://www.cnblogs.com/buryinshadow/p/17001692.html

相关文章

  • 代码随想录算法训练营Day20|654. 最大二叉树、700. 二叉搜索树中的搜索、98. 验证二叉
    代码随想录算法训练营Day20|654.最大二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树654.最大二叉树654.最大二叉树注意题干信息:整数数组nums元素不重复:元......
  • T1408 矩阵嵌套(DAG 记忆化搜索)
    T1408矩阵嵌套​ 有n个矩阵,每个矩阵有长x和宽y。我们定义矩阵A可以嵌套在矩阵B中:A.x>B.x且A.y>B.y或者A.x>B.y且A.y>B.x。我们现在要找一个最长......
  • 带重复节点的前序中序二叉树
    已知一个二叉树的先序遍历序列和中序遍历序列,但其中一些节点的值可能相同。请你返回所有满足条件的二叉树。二叉树在数组中的顺序是任意的。输入[1,1,2],[1,2,1]输出[......
  • 力扣-105-从前序与中序遍历序列构造二叉树/剑指Offer-07
    基本步骤是这样:先看先序序列,可以确定根节点,然后在中序遍历中就可以将二叉树划成左子树和右子树两拨对左右子树递归上述步骤好像直到怎么遍历二叉树,却对怎么重建二叉树......
  • 神经网络架构搜索 材料学习记录
    神经网络架构搜索定义内涵神经网络架构搜索是为给定数据集自动找到一个或多个架构的任务,这些架构将为给定的数据集生成具有良好结果的模型,其本质是在高维空间的最优参数搜......
  • oracle根据某个值搜索所有的表及列名
    1、创建createorreplaceprocedureA_YANDANCHANis--名称A_YANDANCHAN可以改掉v_sqlVARCHAR2(4000);v_tb_columnVARCHAR2(4000);v_cntNUMBER(18,0);......
  • 每日算法之二叉搜索树的第k个节点
    JZ54二叉搜索树的第k个节点题目给定一棵结点数为n二叉搜索树,请找出其中的第k小的TreeNode结点值。返回第k小的节点值即可不能查找的情况,如二叉树为空,则返回-1,或者k......
  • day39_0098.验证二叉搜索树
    0098.验证二叉搜索树classSolution{public:boolisValidBST(TreeNode*root){if(root==NULL)returnfalse;if(root->left){......
  • 二叉树神级遍历!(Morris)
      我们之前说了二叉树基础及二叉的几种遍历方式及练习题本文大纲前序遍历前序遍历的顺序是,对于树中的某节点,先遍历该节点,然后再遍历其左子树,最后遍历其右子树......
  • [leetcode]第 6 天 搜索与回溯算法(简单)
    32-I.从上到下打印二叉树思路没有思路。。看题解要求二叉树从上至下打印,叫做二叉树的广度优先搜索(BFS)。BFS通常借助队列的先入先出特性实现。算法流程:1.特例处理......