二叉搜索树的最小绝对差
思路:既然这是一棵二叉搜索树,那么我们知道,它的后序遍历是一个递增的序列,因此我们可以充分利用这个特性来做题。我们可以设出一个变量,这个变量用来存放最小绝对差,题目说了是绝对差,那么当然是一个正数了,通过双指针加上后序遍历,我们可以不断求的有序序列中前一个元素和当前元素的差值,如果得到的差值小于之前保存的差值(初始化为INT_MAX),那么更新这个差值,这样一来,遍历完这棵树的时候,返回这个变量就可以了。
代码:
/**
* 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 result=INT_MAX;
TreeNode* pre=nullptr;
void traversal(TreeNode*cur){
if(cur==nullptr)return;
//先处理左子树,按照中序遍历去处理,最后取到最小值即可
traversal(cur->left);
//接着处理中间节点,也就是比较当前节点和前一个节点的差值,看看是否比保存的result更小,若更小,跟新rueult
if(pre!=nullptr){
result=min(result,cur->val-pre->val);
}
pre=cur;
//接着处理右子树
traversal(cur->right);
}
int getMinimumDifference(TreeNode* root) {
traversal(root);
return result;
}
};
补充:说明一下,由于采用的是后序遍历,因此当最后一次return的时候,已经遍历完了整颗BST,也就是说result中已经保存了最终的结果。
//这边程序的执行顺序后面还要再捋一捋
501、二叉搜索树中的众数
思路:首先要注意到题目中的众数不止一个,而是可能有多个,这就告诉我们结果集要用一个数组来保存。
这道题目最直白的想法就是用一个map去统计每个元素的值和出现频率,然后将map按照频率进行排序,并从中选出众数,但是这么做并不是最好的做法,实际上我们并不需要额外去申请一个map并排序来选出众数,只需要借助双指针和两个保存频率的变量和一个vector数组就可以了。将双指针一前一后按照中序去遍历,那么如果两指针指向的值相同,我们就计数,如果不同,我们就将计数值归1,如果当前指针指向了空,那么我们直接返回就可以了,因为最终的结果我们存在了vector数组里,所以这里并不需要返回值。
KEY:如果当前计数的值等于我们之前记录的最大计数值,那么向vector数组加入该元素,如果当前计数的值大于我们之前记录的最大计数值,那么我们就把最大计数值改为当前计数值,并将之前vector中保存的结果集清空,再加入当前元素,这样我们最终得到的结果集就包括了所有的众数。
总结:二叉树本身就与链表息息相关,而二叉搜索树又有一些奇妙的特性,因此二叉搜索树结合双指针这个技巧向我们展示了方法之间的传递性。希望以后我能够进一步的扩展双指针的应用场景并总结起来。
代码:
/**
* 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 maxCount=0;
int count=0;
TreeNode* pre=nullptr;
vector<int> result;
void searchBST(TreeNode* cur){
if(cur==nullptr)return;
searchBST(cur->left);//先处理左子树,BST,一般都用中序遍历
//中间节点的处理逻辑
if(pre==nullptr)
{
count=1;//第一个节点,开始计数
}
else if(pre->val==cur->val){
count++;
}
else {
count=1;//新元素与前一个节点元素值不同
}
pre=cur;//pre保存前一个节点
if(count==maxCount)result.push_back(cur->val);
if(count>maxCount){
maxCount=count;
result.clear();
result.push_back(cur->val);
}
searchBST(cur->right);//处理右子树
return;
}
vector<int> findMode(TreeNode* root) {
maxCount=0;
count=0;
TreeNode* pre=nullptr;
result.clear();
searchBST(root);
return result;
}
};
236、二叉树的最近公共祖先
思路:这道题目首先能够让我们意识到的就是我们一定要从下往上去处理节点,才能够找到最近的公共祖先,因此我们应该采用后序遍历的方式来处理节点,其次,本题特别强调过,所给的二叉树中各个节点的元素值互不相同,且最近的公共祖先一定存在。
KEY:首先要明确,必须遍历整颗二叉树才能够得到结果,这是由后序遍历左右中的特性决定的。
其次要清楚,返回公共祖先的几种情况,如果左右指针都不为空,说明各自都找到了一个有效的指针,那么返回根节点(树或者子树的根节点),如果一边为空一边不为空,返回不为空的那一边。
代码:
/**
* 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==p||root==q||root==nullptr)return root;
TreeNode* left=lowestCommonAncestor(root->left, p, q);
TreeNode* right=lowestCommonAncestor(root->right, p, q);
if(left!=nullptr&&right!=nullptr)return root;
if(left!=nullptr&&right==nullptr)return left;
if(left==nullptr&&right!=nullptr)return right;
else return nullptr;
}
};