Day22——二叉树Ⅷ
今日内容:
● 235.二叉搜索树的最近公共祖先
● 701.二叉搜索树中的插入操作
● 450.删除二叉搜索树中的节点
235.二叉搜索树的最近公共祖先
思路:二叉搜索树有序,左子树小于根小于右子树,因此根节点大于最大值,则祖先在左孩子,小于最小值,祖先在右孩子。
此处假设p一直小于q。
TreeNode* recursion(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == nullptr || root->val == p->val || root->val == q->val) return root;
if(root->val >= p->val && root->val <= q->val) return root;
else if(root->val > q->val) return recursion(root->left, p, q);
else if(root->val < p->val) return recursion(root->right, p, q);
return root;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(p->val > q->val) {
return recursion(root, q, p);
}
return recursion(root, p, q);
}
2.
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// if(p->val > q->val) {
// return recursion(root, q, p);
// }
// return recursion(root, p, q);
if (root->val > p->val && root->val > q->val) { // 大于最大值
return lowestCommonAncestor(root->left, p, q);
} else if (root->val < p->val && root->val < q->val) { // 小于最小值
return lowestCommonAncestor(root->right, p, q);
} else return root; // 中间
}
701.二叉搜索树中的插入操作
本来的想法是,中序遍历,因为所有节点都是递增的,当遇到第一个大于val的节点时,将node放在该节点的左侧,可以保证该节点的左侧都小于val和该节点。写了以后发现不可行,因为该节点的孩子不一定为空
思路:
根据二叉搜索树的规律找到节点位置,然后插入。
TreeNode* insertIntoBST(TreeNode* root, int val) {
TreeNode* node = new TreeNode(val);
if(root == nullptr) return node;
TreeNode* cur = root;
TreeNode* pre = root;
while(cur != nullptr) {
pre = cur;
if(cur->val > val) {
cur = cur->left;
} else {
cur = cur->right;
}
}
// cur即是节点位置,但不能直接修改cur
if(val < pre->val) pre->left = node;
else pre->right = node;
return root;
}
450.删除二叉搜索树中的节点
有点难,记录下
==========================================================================
想清楚处理逻辑其实不难,找到元素然后做以下处理
- 删除节点为空节点——直接返回
- 删除节点为叶子节点——直接删除
- 删除节点左孩子为空——返回右孩子
- 删除节点右孩子为空——返回左孩子
- 删除节点左右孩子都不为空——将左孩子挂到右孩子的最左侧叶子节点或将右孩子挂到左孩子最右侧叶子节点,返回相应节点
处理好以上五种情况,再想清楚递归三要素- 递归函数参数和返回值
- 递归结束条件
- 单层递归逻辑
TreeNode* recursion(TreeNode* cur) {
// 为叶子节点——直接删除
if(cur->left == nullptr && cur->right == nullptr)
return nullptr;
// 左孩子为空——返回右孩子
else if(cur->left == nullptr)
return cur->right;
// 右孩子为空——返回左孩子
else if(cur->right == nullptr)
return cur->left;
// 删除节点左右孩子都不为空——将右孩子挂到左孩子最右侧叶子节点
TreeNode* left= cur->left;
while(left->right != nullptr)
left= left->right;
left->right = cur->right;
TreeNode* tmp = cur;
// 返回左孩子
cur = cur->left;
// 删除节点
delete(tmp);
return cur;
}
TreeNode* deleteNode(TreeNode* root, int key) {
if(root == nullptr) return root;
if(root->val > key)
root->left = deleteNode(root->left, key);
else if(root->val < key)
root->right = deleteNode(root->right, key);
else return recursion(root);
return root;
}