给你一个含重复值的二叉搜索树(BST)的根节点 root
,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2] 输出:[2]
示例 2:
输入:root = [0] 输出:[0]
提示:
- 树中节点的数目在范围
[1, 104]
内 -105 <= Node.val <= 105
搜索二叉树是有序的,如果按中序遍历,他就是一个有序的数组!这样去思考就可以了!
遍历有序数组的元素出现频率,从头遍历,那么一定是相邻两个元素作比较,然后就把出现频率最高的元素输出就可以了。
关键是在有序数组上的话,好搞,在树上怎么搞呢?
class Solution {
public:
TreeNode* pre=nullptr;
int Maxcount =0;
int count=0;
vector<int> vec;
void searchBST(TreeNode* cur){
if(cur ==nullptr ) return ;
searchBST(cur->left); //左
//中
if(pre==nullptr){ //目前是root节点
count = 1;
}else if(cur->val == pre->val){ //当pre的值和cur的值相等时,count +1
count +=1;
}else{
count =1 ; //这一步想不出来,但是没有的话,我知道缺了一点东西。这一步说明前面和后面是不一致的,count=1
}
pre =cur;
if(count==Maxcount){
vec.push_back(cur->val);
}
if(count>Maxcount){
Maxcount =count;
vec.clear();
vec.push_back(cur->val);
}
searchBST(cur->right);
return ;
}
vector<int> findMode(TreeNode* root) {
vec.clear();
searchBST(root);
return vec ;
}
};
以上算法,内存占用率比较高,其实可以把push_back换成emplace_back,这样性能会提升很多!
push_back(),他是把x的副本存到容器中来的,所以效率会慢很多。
std::vector<int> vec; int x = 10; vec.push_back(x); // 将x的副本添加到容器中
emplace_back
适用于在容器中构造新元素的情况,这种方式可以避免不必要的复制(或移动)操作。
例子1:
std::vector<int> vec;
vec.emplace_back(10); // 在容器中就地构造新元素
例子2:
#include <vector>
#include <string>
struct Person {
std::string name;
int age;
// 构造函数
Person(const std::string& n, int a) : name(n), age(a) {}
};
int main() {
std::vector<Person> people;
// 使用emplace_back构造新的Person对象
people.emplace_back("Alice", 30); 直接在这里构造新的对象,而不是对象先存在!
people.emplace_back("Bob", 25);
people.push_back(Person("Bob", 25)); 而push_back,则没有构造函数的功能!这是很重要的区别
return 0;
}
总的来说,emplace_back
通常比push_back
更高效,因为它避免了复制或移动临时对象的开销,并允许你通过直接参数构造新的元素。这个可以用来考虑性能优化的时候!