【LeetCode-树】二叉搜索树中的众数
题目描述
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
假定 BST 有如下定义:
- 结点左子树中所含结点的值小于等于当前结点的值
- 结点右子树中所含结点的值大于等于当前结点的值
- 左子树和右子树都是二叉搜索树
示例:
例如:
给定 BST [1,null,2,2],
1
\
2
/
2
返回[2].
题目链接: https://leetcode-cn.com/problems/find-mode-in-binary-search-tree/
思路
二叉搜索树有一个重要的性质:二叉搜索树的中序遍历序列是升序序列。所以我们中序遍历二叉搜索树记录节点值的升序序列,然后根据升序序列找众数。找众数的方法:
- 将序列第一个元素放入结果中,将当前元素出现的最多次数记为curMax并初始化为1,将当前元素的出现次数cnt记为1;
- 从第二个元素开始遍历,如果当前元素和前一个元素相等,则cnt++;
- 如果cnt==curMax,则将当前元素假如结果中;
- 如果cnt>curMax,说明找到了出现次数更多的众数,则将结果清空,将当前元素加入到结果中;
- 如果当前元素和前一个元素不等,则将cnt置为1.
写法一
使用递归,代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> findMode(TreeNode* root) {
if(root==nullptr) return {};
vector<int> v;
inOrder(root, v);
int cnt = 1;
int curMax = 1;
vector<int> ans;
ans.push_back(v[0]);
for(int i=1; i<v.size(); i++){
if(v[i]==v[i-1]){
cnt++;
}else cnt=1;
if(cnt==curMax){
ans.push_back(v[i]);
}else if(cnt>curMax){
curMax = cnt;
ans.clear();
ans.push_back(v[i]);
}
}
return ans;
}
void inOrder(TreeNode* root, vector<int>& v){
if(root==nullptr) return;
inOrder(root->left, v);
v.push_back(root->val);
inOrder(root->right, v);
}
};
- 时间复杂度:O(h+n)
h为树深度,n为节点个数。 - 空间复杂度:O(n)
n为节点个数。
写法二
使用迭代,代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> findMode(TreeNode* root) {
if(root==nullptr) return {};
int maxCnt = INT_MIN;
int cnt = 0; // 保存当前数字的计数
int pre = -1; // 保存前一个数字
vector<int> ans;
stack<pair<TreeNode*, int>> s;
s.push(make_pair(root, 0));
while(!s.empty()){
TreeNode* curNode = s.top().first;
int visit = s.top().second;
s.pop();
if(visit==0){
if(curNode->right!=nullptr) s.push(make_pair(curNode->right, 0));
s.push(make_pair(curNode, 1));
if(curNode->left!=nullptr) s.push(make_pair(curNode->left, 0));
}else{
if(pre!=-1){ // 不是第一个数字
if(curNode->val==pre){
cnt++;
if(cnt>maxCnt){ // 找到了新的众数
ans.clear();
ans.push_back(curNode->val);
maxCnt = cnt;
}else if(cnt==maxCnt){ // 找到了出现次数一样的众数
ans.push_back(curNode->val);
}
}else{
cnt = 1;
if(cnt==maxCnt){ // 防止树中只有两个节点的情况
ans.push_back(curNode->val);
}
}
}else{
cnt = 1;
maxCnt = cnt;
ans.push_back(curNode->val); // 防止树中只有一个节点的情况
}
pre = curNode->val;
}
}
return ans;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(h)
h为树高。