二叉树:求搜索树中的众数( 二 )


应该是先遍历一遍数组 , 找出最大频率(maxCount) , 然后再重新遍历一遍数组把出现频率为maxCount的元素放进集合 。 (因为众数有多个)
这种方式遍历了两遍数组 。
那么我们遍历两遍二叉搜索树 , 把众数集合算出来也是可以的 。
但这里其实只需要遍历一次就可以找到所有的众数 。
那么如何只遍历一遍呢?
如果 频率count 等于 maxCount(最大频率) , 当然要把这个元素加入到结果集中(以下代码为result数组) , 代码如下:
if (count == maxCount) { // 如果和最大值相同 , 放进result中result.push_back(cur->val);}是不是感觉这里有问题 , result怎么能轻易就把元素放进去了呢 , 万一 , 这个maxCount此时还不是真正最大频率呢 。
所以下面要做如下操作:
频率count 大于 maxCount的时候 , 不仅要更新maxCount , 而且要清空结果集(以下代码为result数组) , 因为结果集之前的元素都失效了 。
if (count > maxCount) { // 如果计数大于最大值maxCount = count;// 更新最大频率result.clear();// 很关键的一步 , 不要忘记清空result , 之前result里的元素都失效了result.push_back(cur->val);}关键代码都讲完了 , 完整代码如下:(「只需要遍历一遍二叉搜索树 , 就求出了众数的集合」)
class Solution {private:int maxCount; // 最大频率int count; // 统计频率TreeNode* pre;vector 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中result.push_back(cur->val);}if (count > maxCount) { // 如果计数大于最大值频率maxCount = count;// 更新最大频率result.clear();// 很关键的一步 , 不要忘记清空result , 之前result里的元素都失效了result.push_back(cur->val);}searchBST(cur->right);// 右return ;}public:vector findMode(TreeNode* root) {count = 0;maxCount = 0;TreeNode* pre = NULL; // 记录前一个节点result.clear();searchBST(root);return result;}};迭代法只要把中序遍历转成迭代 , 中间节点的处理逻辑完全一样 。
二叉树前中后序转迭代 , 传送门:

  • 二叉树:听说递归能做的 , 栈也能做
  • 二叉树:前中后序迭代方式的写法就不能统一一下么?
下面我给出其中的一种中序遍历的迭代法 , 其中间处理逻辑一点都没有变(我从递归法直接粘过来的代码 , 连注释都没改 , 哈哈)
代码如下:
class Solution {public:vector findMode(TreeNode* root) {stack st;TreeNode* cur = root;TreeNode* pre = NULL;int maxCount = 0; // 最大频率int count = 0; // 统计频率vector 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中result.push_back(cur->val);}if (count > maxCount) { // 如果计数大于最大值频率maxCount = count;// 更新最大频率result.clear();// 很关键的一步 , 不要忘记清空result , 之前result里的元素都失效了result.push_back(cur->val);}pre = cur;cur = cur->right;// 右}}return result;}};总结本题在递归法中 , 我给出了如果是普通二叉树 , 应该怎么求众数 。
知道了普通二叉树的做法时候 , 我再进一步给出二叉搜索树又应该怎么求众数 , 这样鲜明的对比 , 相信会对二叉树又有更深层次的理解了 。
在递归遍历二叉搜索树的过程中 , 我还介绍了一个统计最高出现频率元素集合的技巧 ,要不然就要遍历两次二叉搜索树才能把这个最高出现频率元素的集合求出来 。
为什么没有这个技巧一定要遍历两次呢?因为要求的是集合 , 会有多个众数 , 如果规定只有一个众数 , 那么就遍历一次稳稳的了 。
最后我依然给出对应的迭代法 , 其实就是迭代法中序遍历的模板加上递归法中中间节点的处理逻辑 , 分分钟就可以写出来 , 中间逻辑的代码我都是从递归法中直接粘过来的 。
求二叉搜索树中的众数其实是一道简单题 , 但大家可以发现我写了这么一大篇幅的文章来讲解 , 主要是为了尽量从各个角度对本题进剖析 , 帮助大家更快更深入理解二叉树
「就酱 , 如果学到了的话 , 就转发给身边需要的同学吧 , 可能他们也需要!」