代码随想录二刷 |二叉树 | 二叉搜索树中的众数

代码随想录二刷 |二叉树 | 二叉搜索树中的众数

  • 题目描述
  • 解题思路
    • 递归法
      • 非二叉搜索树的方式
      • 二叉搜索树的方式
    • 迭代法

题目描述

501.二叉搜索树中的众数

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

假定 BST 有如下定义:

  • 结点左子树中所含结点的值小于等于当前结点的值
  • 结点右子树中所含结点的值大于等于当前结点的值
  • 左子树和右子树都是二叉搜索树

例如:

给定 BST [1,null,2,2],
代码随想录二刷 |二叉树 | 二叉搜索树中的众数_第1张图片

返回[2]。

提示:如果众数超过1个,不需考虑输出顺序

进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)

解题思路

递归法

非二叉搜索树的方式

最直观的方法是遍历这个树,用map统计频率,把频率排个序,最后取前面高频的元素的集合。

  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;
}
  1. 把统计出来的出现频率排序
    将map转化为数组再进行排序(C++中如果使用std::map或者std::multimap可以对key排序,但不能对value排序。),vector里面放的也是pair类型的数据,第一个int为元素,第二个int为出现频率。
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); // 给频率排序
  1. 取高频元素
    此时数组vector中已经是存放着按照频率排好序的pair,那么把前面高频的元素取出来就可以了。
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;
	}
};

你可能感兴趣的:(代码随想录二刷,leetcode,c++)