530 二叉搜索树的最小绝对差, 关键:二叉搜索树和顺序有关的,全都用中序
本题中序套模板,思路秒出。但是传var这里让我学到了。一开始写的是traverse(TreeNode* node, TreeNode* prev, int &min),发现就是prev没传对。后来prev改成global var就对了。
TreeNode* prev;
void traverse(TreeNode* node,int &min){
if(node==nullptr) return;
if(node->left) traverse(node->left, min);
if(prev!=nullptr) {
min=std::min(min,std::abs(node->val-prev->val));
}
prev=node;
if(node->right) traverse(node->right, min);
}
int getMinimumDifference(TreeNode* root) {
//二叉树和顺序有关的,都要用中序遍历
int min=INT_MAX;
prev=nullptr;
traverse(root, min);
return min;
}
我原来传TreeNode* prev的时候总以为自己已经在传地址了,其实不是,可以把TreeNode* 整体理解成一个data type,然后再加上ref才是对的,所有func才在公用一个,TreeNode* & prev
就加一个&符号,WA变AC。不过我看代码随想录都是直接变成global var,其实挺好的,很方便了
void traverse(TreeNode* node, TreeNode* &prev, int &min){
if(node==nullptr) return;
if(node->left) traverse(node->left, prev, min);
if(prev) min=std::min(min,std::abs(node->val-prev->val));
prev=node;
if(node->right) traverse(node->right, prev, min);
}
int getMinimumDifference(TreeNode* root) {
//二叉树和顺序有关的,都要用中序遍历
int min=INT_MAX;
TreeNode* prev=nullptr;
traverse(root, prev, min);
return min;
}
迭代法直接套中序模板,这里就不写了
501 二叉搜索树中的众数
一下想到两种思路,但具体细节思路都略有困惑,看了随想录解答
1 放好再做。本实现熟悉了如何map变vec进行sort
map<int,int> nodemap;
void traverse(TreeNode* node){
if(node==nullptr) return;
if(node->left) traverse(node->left);
nodemap[node->val]++;
if(node->right) traverse(node->right);
}
bool static cmp(const pair<int,int> &a, const pair<int,int> &b){
return a.second>b.second;
}
vector<int> findMode(TreeNode* root) {
//1 模板方法:遍历全部放map,用库函数
traverse(root);
vector<pair<int,int>> vec(nodemap.begin(),nodemap.end());
sort(vec.begin(),vec.end(),cmp);
vector<int> res;
for(int i=0;i<vec.size();i++){
if(vec[i].second==vec[0].second){
res.push_back(vec[i].first);
}
}
return res;
}
2. 边放边做
这里有一个不用遍历两遍找所有众数的技巧
我这个方法自己写了好久,快一个小时,全是逻辑小问题,越写越乱。不想写了,先把随想录的解放在这里:之后抽时间还是要再自己做一次
private:
int maxCount = 0; // 最大频率
int count = 0; // 统计频率
TreeNode* pre = NULL;
vector<int> result;
void searchBST(TreeNode* cur) {
if (cur == NULL) return ;
searchBST(cur->left); // 左
// 中
if (pre == NULL) { // 第一个节点
count = 1;
} else if (pre->val == cur->val) { // 与前一个节点数值相同
count++;
} else { // 与前一个节点数值不同
count = 1;
}
pre = cur; // 更新上一个节点
if (count == maxCount) { // 如果和最大值相同,放进result中
result.push_back(cur->val);
}
if (count > maxCount) { // 如果计数大于最大值频率
maxCount = count; // 更新最大频率
result.clear(); // 很关键的一步,不要忘记清空result,之前result里的元素都失效了
result.push_back(cur->val);
}
searchBST(cur->right); // 右
return ;
}
public:
vector<int> findMode(TreeNode* root) {
count = 0;
maxCount = 0;
TreeNode* pre = NULL; // 记录前一个节点
result.clear();
searchBST(root);
return result;
}
236 Lowest Common Ancestor 最近公共祖先
第一次做公共祖先的题,不会,思路只能出来是后序+回溯。看了思路自己实现的:
主要思路 分两个大类:1 自己不当自己的祖先,那就看左右sub同时都有p/q那就是了
2 自己当自己的祖先,逻辑见代码
实现主要出现的问题和要点:
1.TreeNode *leftn=nullptr;TreeNode *rightn=nullptr;一开始一个case都过不了,就是因为没初始化这俩,也太重要了
2. 递归不能像迭代一样在中间结束,所以确实 返回什么都可以。返回nullptr能让尽快的结束
TreeNode* res=nullptr;
TreeNode* traverse(TreeNode* node,TreeNode* &p, TreeNode* &q){
if(node==nullptr) return node;
TreeNode *leftn=nullptr;
TreeNode *rightn=nullptr;
if (node->left) leftn=traverse(node->left,p,q);
if (node->right) rightn=traverse(node->right,p,q);
//自己当自己的祖先
if((leftn||rightn)&&(node==p||node==q)&& res==nullptr){
res=node;
return nullptr;//return anything could end
}
if(node==p||node==q) return node;
if(leftn && rightn && res==nullptr){
res=node;
return nullptr;//return anything could end
}
else if(leftn && rightn==nullptr){
return leftn;
}
else if(rightn && leftn==nullptr){
return rightn;
}
return nullptr;
}
TreeNode* lowestCommonAncestor(TreeNode* &root, TreeNode* p, TreeNode* q) {
traverse(root,p,q);
return res;
}
上面是我的把两种情况分开讨论的思路。下面是随想录的精简版,能把自己是不是祖先两种情况合并在一起处理:把公共祖先和p,q混在一起返回
if (left != NULL && right != NULL) return root;对于这句,是return 祖先,那在另外的subtree就不可能找到pq了,下次另一边(可能是left或right)一定是null,所以这句话满足了一次后,以后必不可能再满足了,只会随着后序不断往root传,最终做为最后的结果。
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == q || root == p || root == NULL) return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if (left != NULL && right != NULL) return root;
if (left == NULL && right != NULL) return right;
else if (left != NULL && right == NULL) return left;
else { // (left == NULL && right == NULL)
return NULL;
}
}