一、二叉搜索树的最近公共祖先
题目一:235. 二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
使用一个循环来遍历BST。如果
p
和q
的值都小于当前节点的值,则它们都位于当前节点的左子树中,所以向左移动如果它们的值都大于当前节点的值,则它们都位于右子树中,所以向右移动
如果它们分别位于两边,或者其中一个就是当前节点,则当前节点就是它们的最近公共祖先
/*
* @lc app=leetcode.cn id=235 lang=cpp
*
* [235] 二叉搜索树的最近公共祖先
*/
// @lc code=start
/**
* 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) {
TreeNode* current = root;
while (current != nullptr) {
if (p->val < current->val && q->val < current->val) {
current = current->left;
} else if (p->val > current->val && q->val > current->val) {
current = current->right;
} else {
return current;
}
}
return nullptr;
}
};
// @lc code=end
二、二叉搜索树中的插入操作
题目一:701. 二叉搜索树中的插入操作
给定二叉搜索树(BST)的根节点 root
和要插入树中的值 value
,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
如果根节点是
nullptr,
就创建一个新节点并返回它。否则比较
val
和当前节点的值,并递归地在左子树或右子树中插入新值。最后返回根节点,这样就保持了树的结构不变。
/*
* @lc app=leetcode.cn id=701 lang=cpp
*
* [701] 二叉搜索树中的插入操作
*/
// @lc code=start
/**
* 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) {
return new TreeNode(val);
}
if (val < root->val) {
root->left = insertIntoBST(root->left, val);
} else {
root->right = insertIntoBST(root->right, val);
}
return root;
}
};
// @lc code=end
三、删除二叉搜索树中的节点
题目一:450. 删除二叉搜索树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
- 首先找到需要删除的节点;
- 如果找到了,删除它。
基本步骤如下:
定位要删除的节点:根据BST的性质,递归地在左子树或右子树中查找要删除的节点。
删除节点:一旦找到要删除的节点,根据其子节点的不同情况来处理:
- 如果节点是叶子节点,可以直接删除。
- 如果节点只有一个子节点,可以用其子节点替换它。
- 如果节点有两个子节点,可以用其右子树的最小节点(或左子树的最大节点)来替换它,然后删除右子树中的最小节点。
首先递归地在树中找到要删除的节点。
一旦找到,检查它是否有零个、一个或两个子节点,并相应地处理。
对于有两个子节点的情况,找到右子树中的最小节点来替换要删除的节点的值,并递归地删除右子树中的这个最小节点。
/*
* @lc app=leetcode.cn id=450 lang=cpp
*
* [450] 删除二叉搜索树中的节点
*/
// @lc code=start
/**
* 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) {
return nullptr;
}
if (key < root->val) {
root->left = deleteNode(root->left, key);
} else if (key > root->val) {
root->right = deleteNode(root->right, key);
} else {
if (!root->left) {
TreeNode* right = root->right;
delete root;
return right;
} else if (!root->right) {
TreeNode* left = root->left;
delete root;
return left;
}
TreeNode* minNode = getMin(root->right);
root->val = minNode->val;
root->right = deleteNode(root->right, minNode->val);
}
return root;
}
private:
TreeNode* getMin(TreeNode* node) {
while (node->left) {
node = node->left;
}
return node;
}
};
// @lc code=end