LeetCode 235 二叉搜索树的最近公共祖先
题目链接:235. 二叉搜索树的最近公共祖先
做题情况:做完236. 二叉树的最近公共祖先后,把那道题目的代码直接用到本题目中也是可以的,但是没有利用二叉搜索树的特性,这并不是本题的初意,看完卡哥视频和代码随想录书相关部分后,才知道咋样利用这个特性,只要抓住从上往下去递归遍历,第一次遇到cur节点是数值在[p, q]区间中,那么cur就是p和q的最近公共祖先这一点,这道题目就迎刃而解了,具体ac代码如下:
/**
* 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* 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;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
return traversal(root, p, q);
}
};
当然上述代码还可以进行精简写法,具体如下:
/**
* 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) {
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;
}
};
这道题目的迭代写法也是非常简单,具体如下:
/**
* 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) {
while(root){
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 NULL;
}
};
LeetCode 701 二叉搜索树中的插入操作
题目链接:701. 二叉搜索树中的插入操作
做题情况:这道题目和后面的删除二叉搜索树中的节点相比,由于没有改变树的结构,从而简单很多,只要找到插入位置就可以进行插入了,实际上本人觉得迭代写法更容易写出,迭代写法具体代码如下:
/**
* 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==NULL){
TreeNode* node=new TreeNode(val);
return node;
}
TreeNode* cur=root;//当前节点
TreeNode* parent=root;//记录父节点
while(cur!=NULL){
parent=cur;
if(cur->val>val)cur=cur->left;
else cur=cur->right;
}
TreeNode* node=new TreeNode(val);
if(val<parent->val)parent->left=node;
else parent->right=node;
return root;
}
};
看完卡哥视频和代码随想录书相关部分后,才知道递归写法中又涉及到一个重要编程技巧:通过递归函数的返回值完成父子节点的赋值是可以带来便利的,具体有返回值的代码如下:
/**
* 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==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;
}
};
没有返回值的代码如下(明显可以看出复杂了很多):
/**
* 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* parent;
void traversal(TreeNode* cur, int val){
if(cur==NULL){
TreeNode* node=new TreeNode(val);
if(val>parent->val)parent->right=node;
else parent->left=node;
return;
}
parent = cur;
if(cur->val>val)traversal(cur->left,val);
if(cur->val<val)traversal(cur->right,val);
return;
}
TreeNode* insertIntoBST(TreeNode* root, int val) {
parent= new TreeNode(0);
if(root==NULL){
root= new TreeNode(val);
}
traversal(root, val);
return root;
}
};
LeetCode 450 删除二叉搜索树中的节点
题目链接:450. 删除二叉搜索树中的节点
做题情况:独立做这道题目时候,确实挺难的,这里不像上一题,这里涉及到改变树的结构,看完卡哥视频和代码随想录书相关部分后,知道必须要把二叉搜索树中删除节点遇到的情况搞清楚,才能进行写代码,这里共有五种情况,具体参考代码内所注释,具体ac代码如下(抄卡哥的 ):
/**
* 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(root->val==key){
// 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
// 第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点
// 第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
if(root->left==nullptr)return root->right;
else if(root->right==nullptr)return root->left;
else {
// 第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置
// 并返回删除节点右孩子为新的根节点。
TreeNode* cur=root->right;
while(cur->left!=nullptr){
cur=cur->left;
}
cur->left=root->left;
TreeNode* tmp=root;
root=root->right;
delete tmp;
return root;
}
}
if(root->val>key)root->left=deleteNode(root->left, key);
if(root->val<key)root->right=deleteNode(root->right, key);
return root;
}
};
卡哥也给出了普通二叉树的删除方式和本题目迭代法代码,具体可参考所给的,重点掌握上述代码
今天的第三道题目还是有一定难度的感觉,后面需要多加复习和思考,总共花了四五个小时左右。
贵在坚持,加油,共勉