文章内容是自己刷leetcode题目的一些总结。
文章内容参考公众号: 代码随想录。
喜欢的话,希望大家可以点点赞 ^ - ^
一.题目描述
二.题目分析
因为是二叉搜索树,我们依旧可以用验证二叉搜索树中提到的两种方法进行分析。
这里使用两种指针的方法进行求解。
因为我们要找的是众数,二叉搜索树的中序遍历又是有序的,仍然采用中序遍历。
我们用两个指针分别记录当前节点的数值和前一个结点的数值。如果这两个数值相同,给count ++,如果两个数值不相同,count = 1。count记录的是当前数值的个数。
我们记录一个maxcount,当count的值等于maxcount时,将该结果加入ans中;当count的值大于maxcount时,就需要更新结果,应该清除ans,然后将当前节点的数值放进去。maxcount记录的是众数的数值对应的个数。
三.中序遍历递归代码
代码中也有详细的思路与注释。
class Solution {
public:
int count = 0, maxcount = 0;
TreeNode* pre = nullptr;
vector<int> ans;
void trevasal(TreeNode* cur) {
if(cur == nullptr) return ;
trevasal(cur->left); //左
//中
if(pre == nullptr) { //第一个节点
count = 1;
} else if(pre->val == cur->val) { //前后节点值相同
count ++;
} else { //前后节点值不同
count = 1;
}
pre = cur;
if(count == maxcount) { //是当前最大频数,加入结果
ans.push_back(cur->val);
}
if(count > maxcount) { //不是当前最大频数,更新最大频数,清空结果,重新加入
maxcount = count;
ans.clear();
ans.push_back(cur->val);
}
trevasal(cur->right); //右
}
vector<int> findMode(TreeNode* root) {
//如果是二叉搜索树,不是一般的二叉树,思路如下
//1.中序遍历二叉树,遍历结果是递增有序的
//2.统计当前节点的值出现的次数,并将当前节点加入到结果中,用到pre与cur指针
//3.我们可能会遇到频数更高的节点值,更新最大频数,清空结果重新加入
//使用上述方法我们只遍历了一次二叉树
//如果我们先遍历一次统计频数,再遍历一次加入结果,需要遍历两次
ans.clear();
trevasal(root);
return ans;
}
};
四.拓展:如果二叉树不是二叉搜索树
1.解题思路
如果只是一般的二叉树,他没有中序遍历递增的性质,那么我们选择哪一种遍历方式都可以。
我们要统计众数,这里使用map,记录每个节点的频率。
将map按照频率由大到小排序,那么map中第一个元素就是众数,和第一个元素频率相同的后续元素也是众数。
2.递归代码
class Solution {
public:
unordered_map<int, int> myMap;
void trevasal(TreeNode* root) { //前序遍历统计频率
if(root == nullptr) return ;
myMap[root->val] ++;
trevasal(root->left);
trevasal(root->right);
return ;
}
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统计频率
//2.将频率转化为数组进行从大到小排序
//3.统计频率最大的节点值并返回
vector<int> ans;
trevasal(root);
vector<pair<int, int>> vec(myMap.begin(), myMap.end());
sort(vec.begin(), vec.end(), cmp);
ans.push_back(vec[0].first);
for(int i = 1; i < vec.size(); i ++) {
if(vec[i].second == vec[0].second) {
ans.push_back(vec[i].first);
} else {
break;
}
}
return ans;
}
};
五.总结
利用二叉搜索树的中序遍历递增的性质,我们可以很方便的解决许多问题。
在从特殊的二叉搜索树中寻找众数到从一般的二叉树中寻找众数,用到了不同的思路,这与树本身的性质有关,不过核心思想都是统计频率,寻找最大频率。