day 22 第六章 二叉树

● 235. 二叉搜索树的最近公共祖先
● 701.二叉搜索树中的插入操作
● 450.删除二叉搜索树中的节点

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

/*
 * 235. 二叉搜索树的最近公共祖先
中等
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:
 “对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
 */

class Solution_235 {
 public:
  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) {}
  };
  /*
   *
   * 二叉搜索树,有序,从上往下找,只要节点在[p, q]范围内,为其最近公共祖先节点
输入参数为两个指定节点,当前节点,返回结果为公共祖先节点
终止条件为当前节点为空
单层递归逻辑
    判断终止条件,为真返回空
    判断当前节点是否在[p, q]范围内
        若当前节点大于指定节点p,q,说明指定节点在左子树,递归遍历左子树
        若当前节点小于指定节点p,q,说明指定节点在右子树,递归遍历右子树
        若在范围内,返回当前节点
   */
  TreeNode *get(TreeNode *cur, TreeNode *p, TreeNode *q){
      //判断终止条件,为真返回空
      if(!cur)
          return nullptr;
      //判断当前节点是否在[p, q]范围内
      //若当前节点大于指定节点p,q,说明指定节点在左子树,递归遍历左子树
      if(cur->val > p->val && cur->val > q->val){
          TreeNode *node = get(cur->left, p, q);
          if(node)
              return node;
      }
      //若当前节点小于指定节点p,q,说明指定节点在右子树,递归遍历右子树
      if(cur->val < p->val && cur->val < q->val){
          TreeNode *node = get(cur->right, p, q);
          if(node)
              return node;
      }
      //若在范围内,返回当前节点
      return cur;
  }
  TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) {
      return get(root, p, q);
  }
};

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

/*
 * 701. 二叉搜索树中的插入操作
中等
给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。
 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
 */

class Solution_701 {
 public:
  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) {}
  };
  /*
   * 二叉搜索树本质上是有序的,中序遍历,只需找到给定值在该有序数组中的位置,因为有序,该位置必定为空节点,直接插入就行
   *
输入参数为指定节点,当前节点,返回值为新节点
终止条件为空,即找到给定值的位置
单层递归逻辑:
    判断终止条件,为真,返回新建节点
    如果给定值小于当前节点,左子节点遍历
    如果给定值大于当前节点,右子节点遍历
    返回当前节点
   */
  TreeNode *get(TreeNode *root, int val){
      //判断终止条件,为真,返回新建节点
      if(!root){
          TreeNode *node = new TreeNode(val);
          return node;
      }
      //如果给定值小于当前节点,左子节点遍历
      if(val < root->val)
          root->left = get(root->left, val);
      if(val > root->val)
          root->right = get(root->right, val);
      return root;
  }
  TreeNode *insertIntoBST(TreeNode *root, int val) {
      return get(root, val);
  }
};

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

/*
 * 450. 删除二叉搜索树中的节点
中等
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。
 返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
 */

class Solution_450 {
 public:
  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) {}
  };
  /*
   * 五种情况,
    1.未找到指定节点,返回空
    2.指定节点无子节点,直接删掉指定节点就好,返回空
    3.指定节点有左子节点,无右,删除指定节点,返回左子节点
    4.指定节点有右子节点,无左,删除指定节点,返回右子节点
    5.指定节点有两个子节点,需要将指定节点的右子节点挂到其左子节点的右叶子节点上,返回左子节点

输入参数为指定节点,当前节点,返回值为新节点
终止条件为空
单层递归逻辑:
    判断终止条件,为真,返回空
    判断当前节点是否为指定节点
        若是,五种情况
    如果给定值小于当前节点,左子节点遍历
    如果给定值大于当前节点,右子节点遍历
    返回当前节点
   */
  TreeNode *get(TreeNode *root, int key) {
      if (!root)
          return nullptr;
      //判断当前节点是否为指定节点
      if (root->val == key) {
          //2.指定节点无子节点,直接删掉指定节点就好,返回空
          if (!root->left && !root->right) {
              delete root;
              return nullptr;
          }
              //5.指定节点有两个子节点,需要将指定节点的右子节点挂到其左子节点的右叶子节点上,返回左子节点
          else if (root->left && root->right) {
              TreeNode *temp = root->left;
              while (temp->right) {
                  temp = temp->right;
              }
              temp->right = root->right;
              temp = root->left;
              delete (root);
              return temp;
          }
          //3.指定节点有左子节点,无右,删除指定节点,返回左子节点
          else if (root->left) {
              TreeNode *temp = root->left;
              delete root;
              return temp;
          }
              //4.指定节点有右子节点,无左,删除指定节点,返回右子节点
          else if (root->right) {
              TreeNode *temp = root->right;
              delete root;
              return temp;
          }
      }

      //如果给定值小于当前节点,左子节点遍历
      if(key < root->val)
          root->left = get(root->left, key);
      if(key > root->val)
          root->right = get(root->right, key);
      return root;
  }
  TreeNode *deleteNode(TreeNode *root, int key) {

      return get(root, key);
  }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值