给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
结点左子树中所含结点的值小于等于当前结点的值
结点右子树中所含结点的值大于等于当前结点的值
左子树和右子树都是二叉搜索树
我们可以顺序扫描中序遍历序列,用 base 记录当前的数字,用count 记录当前数字重复的次数,用 maxCount 来维护已经扫描过的数当中出现最多的那个数字的出现次数,用 answer 数组记录出现的众数。每次扫描到一个新的元素:
首先更新 base 和 count:
如果该元素和 base 相等,那么 count 自增 11
否则将base 更新为当前数字,count 复位为 11
然后更新 maxCount
如果 maxCountcount=maxCount,那么说明当前的这个数字base出现的次数等于当前众数出现的次数,将 base 加入 answer 数组;
如果 count>maxCount,那么说明当前的这个数字base出现的次数大于当前众数出现的次数,因此,我们需要将maxCount 更新为 count,清空 answer 数组后将 base 加入 answer 数组。
我们可以把这个过程写成一个 handle 函数。这样我们在寻找出现次数最多的数字的时候就可以省去一个哈希表带来的空间消耗。
class Solution {
vector<int>answer;
int base, count, maxCount;
void handle(int x){
//有该元素就增加1
if (x == base) {
++count;
}else{//反正则重置1
count = 1;
base = x;
}
if (count == maxCount) {
answer.push_back(base);
}
if (count > maxCount) {
maxCount = count;
answer = vector<int> {base};
}
}
void deepfirstsearch(TreeNode * root){
if (!root) {
return;
}
deepfirstsearch(root->left);
handle(root->val);
deepfirstsearch(root->right);
}
public:
vector<int> findMode(TreeNode* root) {
deepfirstsearch(root);
return answer;
}
};
时间复杂度O(N),空间复杂度O(N)
002 解法二:记录下每个节点出现的次数
class Solution {
public:
vector<int> findMode(TreeNode* root) {
vector<pair<int, int>> rec;
auto append = [&](int v, int cnt) {
if (cnt <= 0) {
return;
}
if (rec.empty() || cnt > rec.back().second) {
rec.clear();
rec.push_back({v, cnt});
} else if (cnt == rec.back().second) {
rec.push_back({v, cnt});
}
};
int preValue = 0;
int preCnt = 0;
stack<TreeNode *> t;
while (root || !t.empty()) {
while (root) {
t.push(root);
root = root->left;
}
root = t.top();
t.pop();
if (preValue == root->val) {
preCnt++;
} else {
// 如果不相等,那么需要{preValue, preCnt}
// 放到rec中
append(preValue, preCnt);
preValue = root->val;
preCnt = 1;
}
root = root->right;
}
append(preValue, preCnt);
vector<int> ans;
for (auto &p : rec) ans.push_back(p.first);
return ans;
}
};
时间复杂度O(N),空间复杂度O(N)