这里写目录标题
235. 二叉搜索树的最近公共祖先
思路:没有前中后遍历顺序,因为不需要处理中间节点
因为是有序树,所有 如果 中间节点是 q 和 p 的公共祖先,那么 中节点的数组 一定是在 [p, q]区间的。即 中节点 > p && 中节点 < q 或者 中节点 > q && 中节点 < p
1.遇到 cur节点是数值在[p, q]区间中则一定可以说明该节点cur就是q 和 p的公共祖先,但不一定是最近的公共祖先
如果从节点5向左遍历,向右遍历就会出错,因为3和8也是[1,9]区间的,记录第一次出现在区间的值是最近公共祖先
递归
1.确认递归返回值和参数
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
2.确认终止条件
if(root==NULL)return NULL;
3.确认单层递归逻辑
寻找区间[p->val, q->val](注意这里是左闭又闭)
那么如果 cur->val 大于 p->val,同时 cur->val 大于q->val,那么就应该向左遍历(说明目标区间在左子树上)
4.完整代码
class Solution {
public://中左右遍历
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==NULL)return NULL;
if(root->val>p->val&&root->val>q->val)
{
TreeNode* left=lowestCommonAncestor(root->left,p,q);
return left;
}
else if(root->val<p->val&&root->val<q->val)
{
TreeNode* right=lowestCommonAncestor(root->right,p,q);
return right;
}
else
{
return root;
}
}
};
迭代
class Solution {
public://中左右遍历
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
while(root!=NULL)
{
if(root->val>p->val&&root->val>q->val) root=root->left;
else if(root->val<p->val&&root->val<q->val) root=root->right;
else return root;
}
return root;
}
};
701.二叉搜索树中的插入操作
思路:只要按照二叉搜索树的规则去遍历,遇到空节点就插入节点就可以了
递归
1.确认递归返回值和参数
TreeNode* insertIntoBST(TreeNode* root, int val)
2.确认终止条件:终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回。
if(root == nullptr)
{
TreeNode* newnode=new TreeNode(val);
return newnode;
}
3.确认单层递归逻辑:根据插入元素的数值,决定递归方向
if(root->val>val) root->left = insertIntoBST(root->left,val);
if(root->val<val) root->right = insertIntoBST(root->right,val);
完整代码
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root == nullptr)
{
TreeNode* newnode=new TreeNode(val);
return newnode;
}
if(root->val>val) root->left = insertIntoBST(root->left,val);
if(root->val<val) root->right = insertIntoBST(root->right,val);
return root;
}
};
迭代
class Solution {
public:
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root==nullptr)
{
TreeNode*cur=new TreeNode(val);
return cur;
}
TreeNode* cur=root;
while(cur!=nullptr)
{
if(cur->val>val)
{
if(cur->left)cur=cur->left;
else{ cur->left=new TreeNode(val);
break;}
}
if(cur->val<val)
{
if(cur->right)cur=cur->right;
else{
cur->right=new TreeNode(val);
break;}
}
}
return root;
}
};
450. 删除二叉搜索树中的节点
递归思路复杂性高,因为涉及到树的结构改变
1.没找到删除的点
if(root==nullptr)return nullptr;
2删除的点为叶子节点,即左右子树都为空,删除叶子节点
if(root->left==nullptr&&root->right==nullptr)//左右都为空
{
return nullptr;
}
3.删除的点的左子树为空,右子树不为空
if(root->left==nullptr&&root->right!=nullptr)//左为空,右不为空
{
return root->right;
}
4.删除的点的左子树不为空,右子树为空
if(root->left!=nullptr&&root->right==nullptr)//左不为空,右为空
{
return root->left;
}
5.删除的点的左子树不为空,右子树不为空:例如删除7,将7的左子树,放在7右子树上比7大一点最小的数左子树上,再删除7
else
{
TreeNode* cur=root;
while(cur->left!=nullptr)//找到cur最左的子树,
{
cur=cur->left;
}
cur->left=root->left;//将cur的左子树指向root 的左子树
return cur->right;//删除当前节点
}
1.确认递归返回值和参数TreeNode* deleteNode(TreeNode* root, int key)
2.确认终止条件:遇到空返回,其实这也说明没找到删除的节点,遍历到空节点直接返回了if (root == nullptr) return root;
3.确认单层递归逻辑:二叉搜索树中删除节点遇到了五种情况。
4.完整代码
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(root==nullptr)return nullptr;
if(root->val==key)
{
if(root->left==nullptr&&root->right==nullptr)//左右都为空
{
return nullptr;
}
if(root->left!=nullptr&&root->right==nullptr)//左不为空,右为空
{
return root->left;
}
if(root->left==nullptr&&root->right!=nullptr)//左为空,右不为空
{
return root->right;
}
if(root->left!=nullptr&&root->right!=nullptr)
{
TreeNode* cur=root->right;//cur指向root的右子树
while(cur->left!=nullptr)//找到cur最左的子树,
{
cur=cur->left;
}
cur->left=root->left;//将cur的左子树指向root 的左子树
return root->right;//删除当前节点
}
}
if(root->val>key) root->left=deleteNode(root->left,key);
if(root->val<key) root->right=deleteNode(root->right,key);
return root;
}
};