235.二叉搜索树的最近公共祖先
思路:这题可以利用二叉搜索树的特性能更明确的去左右方向找pq。所以什么遍历顺序都可以。
如果pq的值都小于root值,说明pq一定在左子树,去左子树遍历。
如果pq的值都大于root值,则在右子树。
排除以上两种情况,最后一种情况就是pq分别在root左右两侧。此时root一定是pq的最近公共祖先。因为如果往左遍历会错过右子树的节点,往右错过左。
优化:若p为q的父节点就直接返回该节点,if(root==p ||root==q)可以不写,把return root写在所有情况的最后面,这样可以涵盖到pq在root左右两侧和p在q的上面这两种情况。
代码:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL) return NULL;
if(root == p || root == q) return root;
//左
if(root->val > p->val && root->val > q->val){
TreeNode* left = lowestCommonAncestor(root->left,p,q);
if(left!=NULL) return left;
}
//右
if(root->val < p->val && root->val < q->val){
TreeNode* right = lowestCommonAncestor(root->right,p,q);
if(right!=NULL) return right;
}
//中,这种情况pq分别在root左右两边
return root;
}
701.二叉搜索树中的插入操作
思路(递归法):按二叉搜索树特性找到插入位置插入即可,需要考虑到树是空的话,直接插入为根节点。
代码:
void insertnode(TreeNode* node,int val){
if(node == nullptr) return;
if(node->val > val){
insertnode(node->left,val);
if(node->left == nullptr){
node->left = new TreeNode(val);
return;
}
}
if(node->val < val){
insertnode(node->right,val);
if(node->right == nullptr){
node->right = new TreeNode(val);
return;
}
}
}
TreeNode* insertIntoBST(TreeNode* root, int val) {
if(root != nullptr){
insertnode(root,val);
}else{//当前树为空,直接插入为根节点
root = new TreeNode(val);
}
return root;
}
450.删除二叉搜索树中的节点
删除节点的情况分别为5种:
情况1:要删除的节点在树中找不到,遍历后返回空
情况2:要删除的节点左右孩子都为空(叶节点),直接删除该节点,返回null
情况3:要删除的节点左孩子为空,右孩子不为空,把右孩子补到删除节点的位置,然后返回右孩子(删除了节点)。
情况4:要删除的节点左孩子不为空,右孩子为空,把左孩子补到删除节点位置,返回左孩子(和情况3处理规则一样)。
情况5:要删除的节点左右孩子都不为空,cur找到右子树最左下的节点(右子树最小的节点),把要删除节点的左子树移接到cur的左侧,再把要删除的节点的右孩子返回上层。
代码:
TreeNode* deleteNode(TreeNode* root, int key) {
//终止条件,删除节点的情况分类
if(root == NULL) return NULL;//情况1
if(root->val == key){
if(root->left==NULL && root->right==NULL) return NULL;//情况2,这层root是要删除的节点,返回NULL,上层左孩子或者右孩子就是NULL
else if(root->left==NULL && root->right!=NULL) return root->right;//情况3
else if(root->left!=NULL && root->right==NULL) return root->left;//情况4
else if(root->left!=NULL && root->right!=NULL){//情况5
TreeNode* cur = root->right;
while(cur->left != NULL)//cur找到root右子树最左下角的节点即右子树的最小值
cur = cur->left;
//把root的左子树放到cur的左子树中,所以root左子树都比cur值小
cur->left = root->left;
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;
}