问题:“水王”的帖子超过论坛帖子的一半,如何从所有帖子中,找出“水王”的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;
}