算法 查找众数

给定一个大小为n的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 Ln/2」的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例1:
输入:[3,2,3]
输出:3
示例2
输入:[22,1,1,1,2,2
输出:2
说明
本题题面中没有给岀数据范围,但最简单的暴力方法(即枚举数组中的毎个元素,再遍历
一遍数组统计其出现次数,时间复杂度为O(N^2)的算法).会超出时间限制,因此我们需要
找出时间复杂度小于ON^2)的优秀做法。
解法一:排序取中间数
因为根据题目描述可以得到给出测试用例中有超过一半的数是同一个数,即众数。可以想到排序之后中间数一定为我们要找的众数。
代码实现:

int Most_num(vector<int>& vec)
{
    
    
	sort(vec.begin(),vec.end ());
	return vec[vec.size() / 2];//返回中间下标的值
}
int main()
{
    
    
	vector<int> vec = {
    
     1,2,3,4,2,4,2,7,2,9,2,3,2,2,2,2,2 };
	int x = Most_num(vec);
	cout << "Most_num is:" << x << endl;
}

解法二:无序哈希
代码实现:

int Most_num(vector<int>& vec)
{
    
    
	unordered_map<int, int> counts;
	for (auto x : vec)
	{
    
    
		++counts[x];
	}
	int n = vec.size() / 2;
	for (auto &x : counts)
	{
    
    
		if (x.second > n)
		{
    
    
			return x.first;
		}
	}
}

解法三:无序哈希的优化,不用进行二次扫描;
代码实现:

int Most_num(vector<int>& vec)
{
    
    
	unordered_map<int, int> counts;
	int ma = 0, cnt = 0;
	for (auto x : vec)
	{
    
    
		++counts[x];
		if (counts[x] > cnt)
		{
    
    
			ma = x;
			cnt = counts[x];
		}
	}
	return ma;
}

解法四:概率化法
因为本题的特殊性,超过一半的数为相同的,所以概率命中的几率很大。
代码实现:

int n = 0;//概率化寻找次数
int Most_num(vector<int>& vec)//概率化法
{
    
    
	while (1)
	{
    
    
		n++;
		srand(time(NULL));//完全随机化
		int index = rand() % vec.size();//随机取数组值的下标
		int count = 0;
		int ma = vec[index];
		for (int x : vec)
		{
    
    
			if (x == ma)
			{
    
    
				count+=1;
			}
			if (count > vec.size() / 2)//测试用例没有众数时会死循环
			{
    
    
				return ma;
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/Gunanhuai/article/details/109815956