501.二叉搜索树中的众数
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
例如:
返回[2]。
提示:如果众数超过1个,不需考虑输出顺序
进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
最直观的方法是遍历这个树,用map统计频率,把频率排个序,最后取前面高频的元素的集合。
// map key->元素, value->出现频率
void searchBST(TreeNode* cur, unordered_map<int, int>& map) {
if (cur == NULL) return ;
map[cur->val]++; // 统计元素频率
searchBST(cur->left, map);
searchBST(cur->right, map);
return;
}
bool static cmp (const pair<int, int>& a, const pair<int, int>& b) {
return a.second > b.second; // 按照频率从大到小排序
}
vector<pair<int, int>> vec(map.begin(), map.end());
sort(vec.begin(), vec.end(), cmp); // 给频率排序
result.push_back(vec[0].first);
for (int i = 1; i < vec.size(); i++) {
if (vec[i].second == vec[0].second)
result.push_back(vec[i].first);
else break;
}
return result;
整体代码:
class Solution {
private:
void searchBST(TreeNode* cur, unordered_map<int, int>& map) {
if (cur == NULL) return;
map[cur->val]++;
searchBST(cur->left, map);
searchBST(cur->right, map);
return;
}
bool static cmp (const pair<int, int>& a, const pair<int, int>& b) {
return a.second > b.second;
}
public:
vector<int> findMode(TreeNode* root) {
unordered_map<int, int> map;
vector<int> result;
if (root == NULL) return result;
searchBST(root, map);
vector<pair<int, int>> vec(map.begin(), map.end());
sort(vec.begin(), vec.end(), cmp);
result.push_back(vec[0].first);
for (int i = 1; i < vec.size(); i++) {
if (vec[i].second == vec[0].second)
result.push_back(vec[i].first);
else break;
}
return result;
}
};
二叉搜索树的中序遍历是有序的。
在遍历有序数组的元素出现频率时,一般采用从头遍历的方式,让相邻的两个元素作比较,把出现频率最高的元素输出。
在树上也可以这样做,我们设置一个指针指向前一个节点,这样每次cur(当前节点)才能和pre(前一个节点)作比较。
而且初始化的时候pre = NULL,这样当pre为NULL时候,我们就知道这是比较的第一个元素。
代码如下:
if (pre == NULL) { // 第一个节点
count = 1; // 频率为1
} else if (pre->val == cur->val) { // 与前一个节点数值相同
count++;
} else { // 与前一个节点数值不同
count = 1;
}
pre = cur; // 更新上一个节点
本题要求的是最大频率的元素集合,在数组上,要先找出最大频率,然后再遍历一次数组,将最大频率的元素放入集合中。这样就遍历了两次数组。
本题也可以遍历两次数组,但这里提供一种只遍历一次的写法。
如果频率 = 最大频率 (count = maxCount),就将这个元素加入到结果集中:
if (count == maxCount) {
result.push_back(cur->val);
}
这里存在一个问题,如果此时的maxCount不是最大频率就会出现错误,因此要做如下操作:
当频率大于最大频率(count > maxCount)时,不仅要更新 maxCount,而且要清空结果集result,因为当前结果集中的元素已经不是最大频率了。
if (count > maxCount) { // 如果计数大于最大值
maxCount = count; // 更新最大频率
result.clear(); // 晴空result
result.push_back(cur=>val);
}
完整代码如下:
class Solution {
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.push_back(cur->val);
}
if (count > maxCount) {
maxCount = count;
result.clear();
result.push_back(cur->val);
}
searchBST(cur->right);
return;
}
public:
vector<int> findMode(TreeNode* root) {
count = 0;
maxCount = 0;
pre = NULL;
result.claer();
searchBST(root);
return result;
}
};
只要把中序遍历转成迭代,中间节点的处理逻辑完全一样。
class Solution {
public:
vector<int> findMode(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* cur = root;
TreeNode* pre = NULL:
int maxCount = 0;
int count = 0;
vector<int> result;
while (cur != NULL || !st.empty()) {
if (cur != NULL) {
st.push(cur);
cur = cur->left;
} else {
cur = st.top();
st.pop();
if (pre = NULL) {
count = 1;
} else if (pre->val = cur->val) {
count++;
} else {
count = 1;
}
if (count = maxCount) {
result.push_back(cur->val);
}
if (count > maxCount) {
maxCount = count;
result.clear();
result.push_back(cur->val);
}
pre = cur;
cur = cur->right;
}
}
return result;
}
};