代码随想录Day21 | 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先
- 二叉搜索树的最小绝对差
- 二叉搜索树中的众数
- 二叉树的最近公共祖先
二叉搜索树的最小绝对差
文档讲解:代码随想录
视频讲解: 二叉搜索树中,需要掌握如何双指针遍历!| LeetCode:530.二叉搜索树的最小绝对差
状态:
利用转换成数组的方式解决,学习一下利用双指针在中序遍历时求解,由于是二叉搜索树,所以最小绝对差一定是相邻的两数之间求得的。所以双指针就是要使用一个节点来记录当前节点的前一个节点,然后当递归,归到当前节点时(中节点操作),计算差值与此时的最小值比较。
首先需要定义一个全局变量,或者递归中传递一个引用,用来记录当前节点的前一个节点。然后一个全局变量或者引用参数用来记录当前最小值。
我们求取最小值的操作应当放在中节点,即当前节点位置进行,所以当我们的前一个节点不为空时,进行计算更新Minval。然后将当前节点变为前一个节点
class Solution {
private:TreeNode* pre;
public:void GetVector(TreeNode* root ,int& minval){if(root == nullptr) return;if(root->left) GetVector(root->left,minval);//中节点操作if(pre) minval = (root->val - pre->val) < minval ? (root->val - pre->val):minval;pre = root;//将当前节点赋值给前一个节点if(root->right) GetVector(root->right,minval);return ;}
public:int getMinimumDifference(TreeNode* root) {int minval = INT_MAX;GetVector(root,minval);return minval;}
};
二叉搜索树中的众数
定义变量记录当前相等的次数,如果相等就持续++,不等就重新置为1
处理最大值数组的元素
1. 当该元素出现的频率与当前最大值相等,那么直接压入
2. 当频率大于当前最大值,则重新赋值,并清空数组clear,然后压入
class Solution {
private: int maxcount = INT_MIN;int count = 0;TreeNode* pre = nullptr;
public:void GetVector(TreeNode* root, vector<int>& res){if(root == nullptr) return;//左节点GetVector(root->left,res);//中节点//先计算出现次数if(pre == nullptr){//说明是第一个节点count = 1;}else if(pre->val == root->val){count++;}else{//说明当前节点出现了1次count = 1;}pre = root;//处理最大频率压入数组if(count == maxcount){res.push_back(root->val);}//如果count>maxcount更新else if(count > maxcount){maxcount = count;res.clear();res.push_back(root->val);}//右节点GetVector(root->right,res);}
public:vector<int> findMode(TreeNode* root) {vector<int> res;GetVector(root ,res);return res;}
};
这是有序的情况即二叉搜索树,如果是普通二叉树,就需要先遍历获得每个元素以及该元素出现的频率可以使用map来存储,之后对map根据value排序,就需要将当前map转换为vector<pair<int,int>>然后定义一个排序函数,利用sort排序即可,或者可以参考求解前K个频率最大数的方法利用优先队列来求解。前k个高频
二叉树的最近公共祖先
文档讲解:代码随想录
视频讲解: 自底向上查找,有点难度! | LeetCode:236. 二叉树的最近公共祖先
状态
最开始意味是一棵完全二叉树,那题目就变的简单了。对于任何一个节点其父节点的下标都是i/2。
可这道题只是一个普通二叉树,想到之前寻找路径,那么可以通过寻找从根节点到target两个节点的路径数组,然后定义两个指针,从两个数组出发,直到短的数组遍历完,如果有相同值就返回,没有就返回根节点.
class Solution {public: void findTarget(TreeNode* root, vector<TreeNode*>& path, const TreeNode* target,vector<TreeNode*>& res){if(root == nullptr) return ;path.push_back(root);if(root == target){ res = path;return ;} if(root->left){findTarget(root->left,path,target,res);path.pop_back();}if(root->right){findTarget(root->right,path,target,res);path.pop_back();}return ;}
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {vector<TreeNode*> ppath;vector<TreeNode*> qpath;vector<TreeNode*> pres;vector<TreeNode*> qres;findTarget(root,ppath,p,pres);findTarget(root,qpath,q,qres);int temps = pres.size() < qres.size() ? pres.size(): qres.size();for(int i = temps-1;i>=0;i--){if(pres[i] == qres[i]){return pres[i];break;}}return root;}
};
代码随想录里对递归函数是否有返回值做了说明
- 不需要返回值的情况–就是不用对返回值进行处理的情况,比如求得二叉树的所有路径构成的数组,或者是遍历二叉树到一个数组
- 需要返回值的情况
- 遍历树的所有节点:这时候需要记录左节点和右节点递归的值,然后交给中节点进行处理,最后返回中节点。类似题目有求最大深度,或者求最小深度,求二叉树的最近公共祖先
- 只需要遍历一条边,这种情况多发生在判断二叉树中是否有target如果有返回true,然后左子树和右子树根据归的结果返回true或者false