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

501.二叉搜索树中的众数给定一个有相同值的二叉搜索树(BST) , 找出 BST 中的所有众数(出现频率最高的元素) 。
假定 BST 有如下定义:

  • 结点左子树中所含结点的值小于等于当前结点的值
  • 结点右子树中所含结点的值大于等于当前结点的值
  • 左子树和右子树都是二叉搜索树
例如:
给定 BST [1,null,2,2],
二叉树:求搜索树中的众数文章插图
返回[2].
提示:如果众数超过1个 , 不需考虑输出顺序
进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
思路这道题目呢 , 递归法我从两个维度来讲 。
首先如果不是二叉搜索树的话 , 应该怎么解题 , 是二叉搜索树 , 又应该如何解题 , 两种方式做一个比较 , 可以加深大家对二叉树的理解 。
递归法如果不是二叉搜索树如果不是二叉搜索树 , 最直观的方法一定是把这个树都遍历了 , 用map统计频率 , 把频率排个序 , 最后取前面高频的元素的集合 。
具体步骤如下:
  1. 这个树都遍历了 , 用map统计频率
至于用前中后序那种遍历也不重要 , 因为就是要全遍历一遍 , 怎么个遍历法都行 , 层序遍历都没毛病!
这里采用前序遍历 , 代码如下:
// map key:元素 , value:出现频率void searchBST(TreeNode* cur, unordered_mapmap[cur->val]++; // 统计元素频率searchBST(cur->left, map);searchBST(cur->right, map);return ;}
  1. 把统计的出来的出现频率(即map中的value)排个序
有的同学可能可以想直接对map中的value排序 , 还真做不到 , C++中如果使用std::map或者std::multimap可以对key排序 , 但不能对value排序 。
所以要把map转化数组即vector , 再进行排序 , 当然vector里面放的也是pair类型的数据 , 第一个int为元素 , 第二个int为出现频率 。
代码如下:
bool static cmp (const pair // 按照频率从大到小排序}vector> vec(map.begin(), map.end());sort(vec.begin(), vec.end(), cmp); // 给频率排个序
  1. 取前面高频的元素
此时数组vector中已经是存放着按照频率排好序的pair , 那么把前面高频的元素取出来就可以了 。
代码如下:
result.push_back(vec[0].first);for (int i = 1; i < vec.size(); i++) {// 取最高的放到result数组中if (vec[i].second == vec[0].second) result.push_back(vec[i].first);else break;}return result;整体C++代码如下:
class Solution {private:void searchBST(TreeNode* cur, unordered_mapmap[cur->val]++; // 统计元素频率searchBST(cur->left, map);searchBST(cur->right, map);return ;}bool static cmp (const pair}public:vector findMode(TreeNode* root) {unordered_map map; // key:元素 , value:出现频率vector result;if (root == NULL) return result;searchBST(root, map);vector> 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++) {// 取最高的放到result数组中if (vec[i].second == vec[0].second) result.push_back(vec[i].first);else break;}return result;}};「所以如果本题没有说是二叉搜索树的话 , 那么就按照上面的思路写!」
是二叉搜索树「既然是搜索树 , 它中序遍历就是有序的」 。
如图:
二叉树:求搜索树中的众数文章插图
中序遍历代码如下:
void searchBST(TreeNode* cur) {if (cur == NULL) return ;searchBST(cur->left);// 左(处理节点)// 中searchBST(cur->right);// 右return ;}遍历有序数组的元素出现频率 , 从头遍历 , 那么一定是相邻两个元素作比较 , 然后就把出现频率最高的元素输出就可以了 。
关键是在有序数组上的话 , 好搞 , 在树上怎么搞呢?
这就考察对树的操作了 。
在二叉树:搜索树的最小绝对差 中我们就使用了pre指针和cur指针的技巧 , 这次又用上了 。
弄一个指针指向前一个节点 , 这样每次cur(当前节点)才能和pre(前一个节点)作比较 。
而且初始化的时候pre = NULL , 这样当pre为NULL时候 , 我们就知道这是比较的第一个元素 。
代码如下:
if (pre == NULL) { // 第一个节点count = 1; // 频率为1} else if (pre->val == cur->val) { // 与前一个节点数值相同count++;} else { // 与前一个节点数值不同count = 1;}pre = cur; // 更新上一个节点此时又有问题了 , 因为要求最大频率的元素集合(注意是集合 , 不是一个元素 , 可以有多个众数) , 如果是数组上大家一般怎么办?