题目链接:leetcode 235. 二叉搜索树的最近公共祖先
文章讲解:代码随想录 235. 二叉搜索树的最近公共祖先讲解
视频讲解:二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先
思路和解法
题目:
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
想法:
这道题思路比较巧妙,利用二叉搜索树的性质的方法是如果当前节点的值在区间内,就是最近的公共祖先。这里总结一下,如果是返回下面的某个节点,递归调用时就是直接返回调用函数,如果只是修改,那递归时是类似cur -> left = traversal(cur -> left, xxx)这种形式。
/**
* 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) {
// //利用二叉搜索树的性质 可以指导递归的方向
// //自己思考过程偏了 利用二叉搜索树的性质直接得出简单结论,即从上向下寻找,遇到p到q区间的节点就一定是公共祖先
// if (root == nullptr) {
// return root;
// } else 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;
// }
// }
// };
//迭代法 复习一下 再体会一下迭代法
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
//迭代就是指更新root吗?
while (root) {
if (root -> val < p -> val && root -> val < q -> val) {
//往右边搜索
root = root -> right;
} else if (root -> val > p -> val && root -> val > q -> val) {
//往左边搜索
root = root -> left;
} else {
return root;
}
}
return root;
}
};
题目链接:leetcode 701.二叉搜索树中的插入操作
文章讲解:代码随想录 701.二叉搜索树中的插入操作讲解
视频讲解:原来这么简单? | LeetCode:701.二叉搜索树中的插入操作
思路和解法
题目:
给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
想法:
这里总结一下,如果是返回下面的某个节点,递归调用时就是直接返回调用函数,如果只是修改,那递归时是类似cur -> left = traversal(cur -> left, xxx)这种形式。
这里就体现了上面的总结,插入节点非常简单,遍历到插入位置,新建一个节点即可。
/**
* 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 == nullptr) {
TreeNode* node = new TreeNode(val);
return node;
}
if (root -> val < val) {
root -> right = insertIntoBST(root -> right, val);
} else if (root -> val > val) {
root -> left = insertIntoBST(root -> left, val);
}
return root;
}
};
题目链接:leetcode 450.删除二叉搜索树中的节点
文章讲解:代码随想录 450.删除二叉搜索树中的节点讲解
视频讲解:调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点
思路和解法
题目:
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
想法:
这里总结一下,如果是返回下面的某个节点,递归调用时就是直接返回调用函数,如果只是修改,那递归时是类似cur -> left = traversal(cur -> left, xxx)这种形式。
同样体现这个原则,这道题目很容易写错,首先是分出来的五种情况,然后就是最后一种情况的处理稍稍复杂一点,自己写第一遍就写错了。
/**
* 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 == nullptr) return root;
//后写找到删除节点的操作
if (key == root -> val) {
//分多种情况
if (root -> left == nullptr && root -> right == nullptr) {
delete root;
return nullptr;
}
//左子树是空
if (root -> left == nullptr) {
TreeNode* tmp = root -> right;
delete root;
return tmp;
} else if (root -> right == nullptr) {
TreeNode* tmp = root -> left;
delete root;
return tmp;
} else {
//都不为空
//找到右子树最左边节点
TreeNode* cur = root -> right;
//这里写错了,cur->left如果是空指针,那cur走到空指针赋值没有意义,因为上一个节点
//并没有指向下一个节点
while (cur -> left != nullptr) {
cur = cur -> left;
}
cur -> left = root -> left;
TreeNode* tmp = root -> right;
delete root;
return tmp;
}
}
//先写前面的递归过程
if (key > root -> val) {
//往右边搜索
root -> right = deleteNode(root -> right, key);
} else if (key < root -> val) {
//往左搜索
root -> left = deleteNode(root -> left, key);
}
return root;
}
};