235. 二叉搜索树的最近公共祖先
相对于 二叉树的最近公共祖先 本题就简单一些了,因为 可以利用二叉搜索树的特性。本题迭代和递归方法都简单,因为有序。
题目链接/文章讲解:代码随想录
算法思路:利用二叉搜索树的特性:左<根<右。 遍历二叉搜索树,如果当前节点比P,Q的节点都大,则P,Q的公共祖先向该节点左子树寻找,反之,如果当前节点比P,Q的节点都小,则P,Q的公共祖先向该节点右子树寻找,当找到第一个在P、Q大小之间的节点,即为最小公共祖先。
应用场景:求二叉搜索树最近公共祖先,因为 有序。
递归法
递归三部曲如下:
- 确定递归函数返回值以及参数
参数就是当前节点,以及两个结点 p、q。
返回值是要返回最近公共祖先,所以是TreeNode * 。
代码如下:
TreeNode* traversal(TreeNode* cur, TreeNode* p, TreeNode* q)
- 确定终止条件
遇到空返回就可以了,代码如下:
if (cur == NULL) return cur;
- 确定单层递归的逻辑
在遍历二叉搜索树的时候就是寻找区间[p->val, q->val](注意这里是左闭右闭)
那么如果 cur->val 大于 p->val,同时 cur->val 大于q->val,那么就应该向左遍历(说明目标区间在左子树上)。需要注意的是此时不知道p和q谁大,所以两个都要判断
整体代码:
class Solution {
private:
TreeNode* traversal(TreeNode* cur,TreeNode* p,TreeNode* q) {
if (cur == NULL) return cur;
// 中
if (cur->val > p->val && cur->val > q->val) { // 左
TreeNode* left = traversal(cur->left, p, q);
if (left != NULL) {
return left;
}
}
if (cur->val < p->val && cur->val < q->val) {
TreeNode* right = traversal(cur->right, p, q);
if (right != NULL) {
return right;
}
}
return cur;
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
return traversal(root, p, q);
}
};
701.二叉搜索树中的插入操作
本题比想象中的简单,大家可以先自己想一想应该怎么做,然后看视频讲解,就发现 本题为什么比较简单了。题目链接/文章讲解:代码随想录
学完后的感想:二叉搜索树插入节点的思路真的简单,因为二叉树一有序起来,思路真的很好想,且插入节点不用考虑改变树的结构。
算法思路:插入的任意新节点往叶子节点插就行了。 任意节点在叶子处都能找到位置,因为只要满足二叉搜索树:左<根<右 的特性就行。
应用场景:二叉搜索树,插入节点
递归法
递归三部曲:
- 确定递归函数参数以及返回值
参数就是根节点指针,以及要插入元素,这里递归函数要不要有返回值呢?
可以有,也可以没有,最好有,因为有返回值的话,可以利用返回值完成新加入的节点与其父节点的赋值操作。
递归函数的返回类型为节点类型TreeNode * 。
代码如下:
TreeNode* insertIntoBST(TreeNode* root, int val)
- 确定终止条件
终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回。
代码如下:
if (root == NULL) {
TreeNode* node = new TreeNode(val);
return node;
}
这里把添加的节点返回给上一层,就完成了父子节点的赋值操作了,详细再往下看。
- 确定单层递归的逻辑
此时要明确,需要遍历整棵树么?
不用。搜索树是有方向了,可以根据插入元素的数值,决定递归方向。
代码如下:
if (root->val > val) root->left = insertIntoBST(root->left, val);
if (root->val < val) root->right = insertIntoBST(root->right, val);
return root;
下一层将加入节点返回,本层用root->left或者root->right将其接住。
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if (root == NULL) {
TreeNode* node = new TreeNode(val);
return node;
}
if (root->val > val) root->left = insertIntoBST(root->left,val);
if (root->val < val) root->right = insertIntoBST(root->right,val);
return root;
}
};
450.删除二叉搜索树中的节点
学完后的想法:基于我目前对二叉树的掌握情况,本题偏难,不在我一刷掌握范围内,只大概听了一下解题思路 。(多提一句,普通二叉树节点的删除比二叉搜索树还难)
解题思路挺好想的,无非就五种情况:文字看不懂可直接看视频讲解,视频讲的很清楚
1.没有找到要删除的节点,
2.删的是叶子节点,
3.删的节点左子树为空右子树不为空(此时父节点直接略过删除节点指向右子树节点),
4.删的节点左子树不为空右子树为空(此时父节点直接略过删除节点指向左子树节点),
5.左右子树均不为空(此时父节点直接略过删除节点指向右子树节点,其左子树节点接入右子树节点的左子树下)