您的位置:首页 > 财经 > 金融 > 算法day18|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

算法day18|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

2024/12/22 17:57:04 来源:https://blog.csdn.net/2402_84438596/article/details/141824079  浏览:    关键词:算法day18|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

算法day18|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

  • 235. 二叉搜索树的最近公共祖先
    • 1.一般性解法
    • 2.递归法
    • 3.迭代法
  • 701.二叉搜索树中的插入操作
    • 1.递归法
    • 2.迭代法
  • 450.删除二叉搜索树中的节点

235. 二叉搜索树的最近公共祖先

1.一般性解法

class Solution {
public:TreeNode* traversal(TreeNode* root, TreeNode* p, TreeNode* q){if(root==NULL)return root;if(root==p||root==q)return root;TreeNode* left=traversal(root->left,p,q);TreeNode* right=traversal(root->right,p,q);if(left!=NULL&&right!=NULL)return root;else if(left==NULL&&right!=NULL)return right;else if(left!=NULL&&right==NULL)return left;elsereturn NULL;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {return traversal(root,p,q);}
};

注意

else if(left!=NULL&&right==NULL)return left;

这里返回的是left,而不是root->left。我们需要返回的是从左孩子传上来的值,而不是左孩子结点。

2.递归法

class Solution {
public:TreeNode* traversal(TreeNode* root, TreeNode* p, TreeNode* q){if(root==NULL)return NULL;if(root->val>p->val&&root->val>q->val){TreeNode*left=traversal(root->left,p,q);if(left!=NULL)return left;}else if(root->val<p->val&&root->val<q->val){TreeNode*right=traversal(root->right,p,q);if(right!=NULL)return right;}return root;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {return traversal(root,p,q);}
};

二叉搜索树的另一个利用思路:除了利用二叉树搜索树的中序遍历之外,我们也可以直接利用二叉搜索树在树上的性质:左<中<右。由于没有用到中序遍历的递增序列,所以在递归的时候可以不使用中序遍历,直接用它的性质来接就行了

核心思路:如果结点值 > p和q的值,那么说明p和q在该节点左边,所以需要向左递归;如果结点值 < p和q的值,那么说明p和q在该节点右边,所以需要向右递归;如果节点值在p和q之间,那么这个结点就是最近的公共祖先。

代码细节:如果函数有返回值,那么在if和else之外一定还需要有一个return,所以这样是错的:

else if(root->val<p->val&&root->val<q->val){TreeNode*right=traversal(root->right,p,q);if(right!=NULL)return right;}
elsereturn root;}

但是改成这样就对了,在 if 和 else 之外再加一个return:

else if(root->val<p->val&&root->val<q->val){TreeNode*right=traversal(root->right,p,q);if(right!=NULL)return right;}
else
{return root;
}     return NULL;}

3.迭代法

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;}elsereturn root;}return NULL;}
};

701.二叉搜索树中的插入操作

1.递归法

比较简单,代码如下:

class Solution {
public:void traversal(TreeNode* &root, int val){if(root==nullptr){root=new TreeNode(val);return;}if(root->val<val){if(root->right)traversal(root->right,val);else{TreeNode*node=new TreeNode(val);root->right=node;}}if(root->val>val){if(root->left)traversal(root->left,val);else{TreeNode*node=new TreeNode(val);root->left=node;}}return;}TreeNode* insertIntoBST(TreeNode* root, int val) {traversal(root,val);return root;}
};

**核心思路:**当结点值 > root,且右孩子不为空,则向右递归。若右孩子为空,则直接插入,作为该节点的右孩子;当节点值 < root时同理。

易错:

void traversal(TreeNode* &root, int val)

这里需要“带回去”,所以要加上&。

2.迭代法

class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {if(root==nullptr){root=new TreeNode(val);return root;}TreeNode*cur=root;TreeNode*parent=cur;while (cur != NULL) {parent = cur;if (cur->val > val) cur = cur->left;else cur = cur->right;}TreeNode*node=new TreeNode(val);if(parent->val<val)parent->right=node;elseparent->left=node;return root;}
};

思路与递归法一致。

450.删除二叉搜索树中的节点

这题难度不小,第一遍尽量理解:

class Solution {
public:TreeNode* traversal(TreeNode* root, int key){if(root==nullptr)return nullptr;if(root->val==key){if(root->left==nullptr&&root->right==nullptr){delete root;return nullptr;}else if(root->left!=nullptr&&root->right==nullptr){TreeNode*temp=root->left;delete root;return temp;}else if(root->left==nullptr&&root->right!=nullptr){TreeNode*temp=root->right;delete root;return temp;}else if(root->left!=nullptr&&root->right!=nullptr){TreeNode*cur=root->right;TreeNode*temp=root->right;while(cur->left)cur=cur->left;cur->left=root->left;delete root;return temp;}}if(root->val>key)root->left=traversal(root->left,key);if(root->val<key)root->right=traversal(root->right,key);return root;}TreeNode* deleteNode(TreeNode* root, int key) {return traversal(root,key);}
};

总体思路:

  • 参数和返回值正常

  • 终止条件:

    这题的终止条件是重中之重,因为核心条件的判断也纳入了终止条件,即只要符合某种条件就终止。这个条件就是节点值等于key,因为只要节点值等于key就不用再继续递归了。所以真正删除的核心操作就在终止条件里,一共有4种情况:

    • 左右孩子都空,即为叶节点

    • 左孩子空,右孩子不空

    • 左孩子不空,右孩子空

    • 左右孩子都不空(注意这里可以有两种处理逻辑,只要能满足二叉搜索树的定义即可

  • 单层递归逻辑:不用对当前结点做处理,只有满足一定条件时才会有处理(即终止条件)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com