1. 二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
- 二插搜索树, 从上往下遍历的话,当遇到根节点的值在区间 [p, q] 内,则一定是最近公共祖先(注意这里是开区间)
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 二叉搜索树: 最近父节点一定是在 [p q] 区间内的
// 因此从上往下遍历,只要遇到在这个区间内的,就一定是最近公共祖先
if(root == NULL) return root;
if((root->val >= p->val && root->val <= q->val) || (root->val <= p->val && root->val >= q->val)){
return root;
}
TreeNode* leftNode = lowestCommonAncestor(root->left, p, q);
TreeNode* rightNode = lowestCommonAncestor(root->right, p, q);
return leftNode != NULL ? leftNode : rightNode;
}
};
2.二叉搜索树中的插入操作
给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
- 判断左右子节点的版本
*/
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root == NULL){
TreeNode* node = new TreeNode(val);
return node;
}
// 前序遍历
if(val < root->val){
if(root->left == NULL){
TreeNode* node = new TreeNode(val);
root->left = node;
return root;
}
insertIntoBST(root->left, val);
}else{
if(root->right == NULL){
TreeNode* node = new TreeNode(val);
root->right = node;
return root;
}
insertIntoBST(root->right, val);
}
return root;
}
};
- 判断当前节点的版本
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root == NULL) return new TreeNode(val);
if(root->val > val) root->left = insertIntoBST(root->left, val);
if(root->val < val) root->right = insertIntoBST(root->right, val);
return root;
}
};
3.删除二叉树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
class Solution {
public:
// 删除当前节点n(如果有左右子节点则称为p和q)
// 1. 如果没有左右节点,直接删除
// 2. 左右节点都不为空,将q代替n,q旧的左子树需要移动到 p的右子树上, q的left需要变为p
// 3. 如果只有左节点没有右边节点: 直接将p代替n
// 4. 只有右节点没有左节点: 直接将q代替n
TreeNode* deleteNode(TreeNode* root, int key) {
if(root == NULL) return root;
// 前序遍历
if(root->val == key){
// 如果没有左右节点
if(root->left == NULL && root->right == NULL) return NULL;
// 如果只有左节点, 没有右节点, 直接返回root->left, 代替以前的root
else if(root->left != NULL && root->right == NULL){
return root->left;
}
// 如果只有右节点,没有左节点, 直接返回root->right 代替以前的root
else if(root->left == NULL && root->right != NULL){
return root->right;
}
// 如果左右节点都存在
else if(root->left != NULL && root->right != NULL){
// root->right->right 不变
// 将root—>right->left 移动到 root->left->right上
TreeNode* cur = root->left;
while(cur->right != NULL){
cur = cur->right;
}
cur->right = root->right->left;
// 将root->right->left清除
root->right->left = root->left;
return root->right; // 还需要进行后续的操作
}
}
root->left = deleteNode(root->left, key);
root->right = deleteNode(root->right, key);
return root;
}
};