代码随想录day22 二叉树开始进入无固定方法阶段

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

题目

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树:  root = [6,2,8,0,4,7,9,null,null,3,5]

代码随想录day22 二叉树开始进入无固定方法阶段_第1张图片

示例 1:

  • 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
  • 输出: 6
  • 解释: 节点 2 和节点 8 的最近公共祖先是 6。

思考

这题用通用方法二叉树的公共祖先肯定能做,但是既然是二叉搜索树,那么肯定要根据它的特点来解,这个特点就是如果p、q都大于root就搜右子树,小于就搜左子树,因为二叉搜索树左子树元素都小于root,右子树都大于root,那么当p大于root,q小于root或者p小于q大于时,证明要返回的最近公共祖先就是root,因为如果是次近公共祖先的话,肯定满足之前两个条件,还要继续遍历

代码

class Solution {

public:

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {

        if(root == NULL) return NULL;

        //利用二叉搜索树的性质,如果p、q都小于root就向左遍历,如果大于就向右遍历,如果处于root处于中间则root一定是最近公共祖先

        if(root->val > p->val && root->val > q->val) {

            TreeNode* left = lowestCommonAncestor(root->left, p, q);

            if(left != NULL) return left;

        }

        if(root->val < p->val && root->val < q->val) {

            TreeNode* right = lowestCommonAncestor(root->right, p, q);

            if(right != NULL) return right;

        }

        return root;

    }

};

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

题目

给定二叉搜索树(BST)的根节点和要插入树中的值,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据保证,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回任意有效的结果。

代码随想录day22 二叉树开始进入无固定方法阶段_第2张图片

思考

这题初看有点懵,想着根据二叉搜索树的特性,如果val大于root就向右遍历,小于就向左遍历,但是怎么插入呢,看完卡哥视频才发现,其实任何插入的点都能在叶子结点找到其位置,那么当遍历root到nullptr时,返回要插入的点,这样就做到了插入的操作,接着在每一层递归都返回root就行

题目

class Solution {

public:

    TreeNode* insertIntoBST(TreeNode* root, int val) {

        TreeNode* node = new TreeNode(val);

        if(root == nullptr) return node;//任意值都能在二叉树的叶子结点的左右子树找到位置

        if(root->val < val) root->right = insertIntoBST(root->right, val);

        else root->left = insertIntoBST(root->left, val);

        return root;

    }

};

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

题目

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

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

首先找到需要删除的节点; 如果找到了,删除它。 说明: 要求算法时间复杂度为 $O(h)$,h 为树的高度。

示例:

代码随想录day22 二叉树开始进入无固定方法阶段_第3张图片

思考

本以为可以用插入结点的方式来做,没想到啪啪打脸,因为删除结点需要改变二叉树结构,看完卡哥视频才发现需要考虑五种情况:

1、没找到对应值,直接return nullptr

2、找到对应值并且该结点左右子树都为空(即叶结点),那么直接把该结点变为空,返回nullptr

3、找到对应值并且该结点左子树不为空右子树为空,那么返回root->left,因为要把左子树直接插到root左边

4、找到对应值并且该结点左子树为空右子树不为空,那么返回root->right,因为要把右子树直接插到root右边

5、找到对应值并且该结点左右子树都不为空,这里卡哥给出的方法是先把该结点左子树用一个node替代号,然后找到该结点右子树最接近该结点值的结点,即右子树最左边的值,然后将node插到找到的结点的左边,这里用找到左子树最大值然后将右子树插入应该也可以

代码

class Solution {

public:

    TreeNode* deleteNode(TreeNode* root, int key) {

        if(root == nullptr) return nullptr;

        if(root->val == key) {

            if(root->left == nullptr && root->right == nullptr) return nullptr;

            else if(root->left != nullptr && root->right == nullptr) return root->left;

            else if (root->left == nullptr && root->right != nullptr) return root->right;

            else {

                TreeNode* node = root->right;

                while(node->left != nullptr) node = node->left;

                node->left = root->left;

                return root->right;

            }

        }

        if(root->val < key) root->right = deleteNode(root->right, key);

        else root->left = deleteNode(root->left, key);

        return root;

    }

};

你可能感兴趣的:(算法,b树,数据结构)