LeetCode 530 二叉搜索树的最小绝对差
题目链接:https://leetcode.cn/problems/minimum-absolute-difference-in-bst/
思路:
自己的思路:二叉搜索树通过中序遍历后可以得到一个有序数组,因此先遍历出一个有序数组然后再进行两两之间求最小值。
双指针法:利用一个指针pre指向cur指针的前一个节点
![](https://img-blog.csdnimg.cn/img_convert/dc5d4893c2cad07e1fdfc0a59f3e0587.png)
注:遇到在二叉搜索树上求什么最值,求差值之类的,都要思考一下二叉搜索树可是有序的,要利用好这一特点。
代码:
中序遍历暴力法
/**
* 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:
int min = INT_MAX;
vector<int>result;
int getMinimumDifference(TreeNode* root) {
if(!root) return 0;
result.clear();
traversal(root);
for(int i = 1;i<result.size();i++)
{
min = (result[i]-result[i-1])>min?min:(result[i]-result[i-1]);
}
return min;
}
void traversal(TreeNode *root)
{
if(root==nullptr) return;
traversal(root->left);
result.push_back(root->val);
traversal(root->right);
}
};
双指针法
/**
* 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:
int Min = INT_MAX;
TreeNode *pre = nullptr;
int getMinimumDifference(TreeNode* root) {
if(!root) return 0;
traversal(root);
return Min;
}
void traversal(TreeNode *cur)
{
if(!cur) return;
traversal(cur->left);
if(pre)
{
Min = min(Min,abs(cur->val-pre->val));
}
pre = cur; // 回溯的过程,此时pre指向cur的前一个节点
traversal(cur->right);
}
};
总结
通过二叉搜索树的特性,暴力解法一下子就想到了。双指针的方法需要好好掌握。
LeetCode 501 二叉搜索树中的众数
题目链接:https://leetcode.cn/problems/find-mode-in-binary-search-tree/
思路:
自己的思路:
将二叉搜索树遍历出来,然后用map去统计每一个数的出现频率,最后取频率最高的一个或某几个数。(也适用于普通二叉树)
双指针法:
通过中序遍历来完成,因为双指针法中序遍历的话,pre一直会指向cur的前一个节点,只要比较cur节点和pre节点的值是否相同即可。此时,还要注意,因为要找的是频率最大的众数们。所以还要确定最大频率。
代码:
暴力解法
/**
* 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:
vector<int> findMode(TreeNode* root) {
unordered_map<int,int>map; // key:元素 value:频率
vector<int>result;
if(!root) return result;
traversal(root,map);
vector<pair<int,int>>vec(map.begin(),map.end());
sort(vec.begin(),vec.end(),cmp);
for(int i = 0;i<vec.size();i++)
{
if(vec[i].second==vec[0].second)
result.push_back(vec[i].first);
else
break;
}
return result;
}
void traversal(TreeNode *root,unordered_map<int,int>&map)
{
if(!root) return;
map[root->val]++;
traversal(root->left,map);
traversal(root->right,map);
return;
}
bool static cmp (const pair<int, int>& a, const pair<int, int>& b)
{
return a.second > b.second;
}
};
双指针法
/**
* 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 {
private:
int count = 0;
int Maxcount = 0;
TreeNode *pre = nullptr;
vector<int>result;
void SearchBST(TreeNode *cur)
{
// 终止条件
if(!cur) return;
// 左
SearchBST(cur->left);
// 中
if(!pre) // pre不存在代表此时cur是第一个节点
count = 1;
else if(pre->val==cur->val)
count++;
else
count = 1; // 说明pre和cur不一样了,需要更新下一个节点的频率
pre = cur; // 更新上一个节点;
if(count==Maxcount)
result.push_back(cur->val);
if(count>Maxcount)
{
Maxcount = count;
result.clear(); // 清除之前“频率最大值”记录的元素
result.push_back(cur->val); // 重新将此时“频率最大值”的元素记录下来
}
// 右
SearchBST(cur->right);
return ;
}
public:
vector<int> findMode(TreeNode* root) {
result.clear();
if(!root) return result;
SearchBST(root);
return result;
}
};
总结
双指针法还需要多加学习和练习。
LeetCode 236 二叉树的最近公共祖先
题目链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/
思路:
因为要从底部往上遍历,即从下网上遍历,因此需要用到回溯,而后序遍历是天然的回溯。
在这里要对整棵树进行处理,而不是单独处理某一边,因为后序遍历是左右中,只有把左和右都得到了才可以去处理中的情况。
遍历整棵树的代码
left = 递归函数(root->left); // 左
right = 递归函数(root->right); // 右
left与right的逻辑处理; // 中
搜索某一条边的做法
if (递归函数(root->left)) return ;
if (递归函数(root->right)) return ;
两种情况:
情况一:
![](https://img-blog.csdnimg.cn/img_convert/2ee52a62783ce0cefc1c1273c1cdde74.png)
情况二:
![](https://img-blog.csdnimg.cn/img_convert/cc983d336d254cfab297635d6819ad5d.png)
完整流程图:
![](https://img-blog.csdnimg.cn/img_convert/4f8a4fa2e871d3dd0470ea5a82515008.png)
代码:
/**
* 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==nullptr) return nullptr;
// 第二种情况,找到了p或者q
if(root==p||root==q) return root;
// 开始后序遍历
// 左
TreeNode *left = lowestCommonAncestor(root->left,p,q);
// 右
TreeNode *right = lowestCommonAncestor(root->right,p,q);
// 中
if(left!=nullptr&&right!=nullptr) return root; // 说明当前父节点的左右子树分别存在p和q,所以此时的父节点是最近公共祖先
if(left==nullptr&&right!=nullptr) return right; // 说明当前父节点的右子树存在p或者q,继续向上回溯
else if(left!=nullptr&&right==nullptr) return left; // 同上
else return nullptr; // 此父节点不存在p和q
}
};
总结
遇到要从下往上遍历整棵树----采用后序遍历(天然的回溯)。并且需要用变量接住左和右传回来的值,从而进行中的处理。
今日总结:
继续加油!只想到暴力解法还不够,还要熟悉双指针和回溯的思想。