算法:水王问题

问题:“水王”的帖子超过论坛帖子的一半,如何从所有帖子中,找出“水王”的ID?

方法一:两两相消

思路:我们先找数组中的第一个作为候选者,然后找它的下一个,如果一样就次数+1,不一样就相消,当遍历完一边这个数组之后,候选者就是我们找的水王

#include<iostream>
#include<stdlib.h>
#include<stdbool.h>
#include<string>
#include<vector>
#include<string.h>
#include <algorithm> sort
using namespace std;
//水王问题
//两两相消法,why?因为有一个数出现的次数大于数组中的一半,不相同的数据
//相消之后剩下的一定是这个数
void slove4(int* a,int n)
{
	//候选数,先定位第一个元素
	int candidate = a[0];
	//出现次数
	int nTimes = 1;
	//扫描数组
	for (int i = 1; i <= n; i++)
	{
		if (nTimes == 0)
		{
			candidate = a[i];
			nTimes = 1;
			continue;
		}
		if (a[i] == candidate)
		{
			nTimes++;
		}
		else {
			nTimes--;
		}
	}
	cout << candidate << endl;
}
int main(int argc, int* argv[])
{
	int a[] = { 0,1,8,2,8,3,8,4,8,8 };
	int n = sizeof(a) / sizeof(int);
	slove4(a,n-1);
	return 0;
}

方法二:暴力求解发

我们将数组中的每个元素都进行计数操作,找到次数大于数组个数一半的数(哈希表)

水王Plus版本(如果水王发表出来的帖子正好等于原数组数据的一边的时候,找到谁是水王)

思路:如果水王发出来的贴子正好是帖子总数的一边,这说明了啥,xdm?说明帖子的总数一定是偶数,我们还是用上面的两两相消法,如果最后相消成0,可能有两种情况,可能最后一个元素是水王,那么正好消成零,但是我们如果遍历的时候用count计数(如果值等于最后一个元素就+1),到时候如果遍历一遍之后,count=数组的一半,那么最后一个元素为水王,还有一种可能,最后一个不是水王,但是当遍历到最后一个元素之后,和前面的候选者一相消,计数变成0,那么前面候选者一定是水王,不可能是其他的元素就消不成零了,如果最后不是0,那候选者就是水王

#include<iostream>
#include<stdlib.h>
#include<stdbool.h>
#include<string>
#include<vector>
#include<string.h>
#include <algorithm> sort
using namespace std;
void slove4(int* a,int n)
{
	int candidate = a[0];
	int nTimes = 1;
	int countOfLast = 0;//对最后一个元素来计数,可能最后一个元素为水王
	int N = n;
	for (int i = 0; i <= n; i++)
	{
		if (a[i] == a[N - 1])//如果i上的元素等于最后一个元素,那就+1
		{
			countOfLast++;
		}
		if (nTimes == 0)//相消为0后,候选后移一位
		{
			candidate = a[i];
			nTimes = 1;
			continue;
		}
		if (a[i] == candidate)//等于候选+1
		{
			nTimes++;
		}
		else {
			nTimes--;
		}
	}
	if (countOfLast == (n + 1) / 2)//当最后一个元素为数组中元素个数的
		//一半的时候,那最后一个元素为水王
	{
		cout << a[n] << endl;
	}
	else {//否则候选为水王
		cout << candidate << endl;
	}
}
int main(int argc, int* argv[])
{
	int a[] = { 0,1,8,2,8,3,8,4,8,8 };
	int n = sizeof(a) / sizeof(int);
	slove4(a,n-1);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值