● 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);
}
};