1. 问题描述
基础问题:找出发帖数超过帖子总数一半的ID.
拓展问题:有三人发帖数都超过了帖子总数目N的1/4,找出他们的ID.
2. 算法与解析
我们可以先排序然后找出中间的那个ID,但可以考虑避免排序来改进时间复杂度。
每次从列表删除两个不相同的ID,剩余的相同ID就是找到的“水王”。
Type Find(Type * ID, int N){
Type candidate;
//nTimes 是一个计数器。
int nTimes, i;
for (i = nTimes = 0; i < N; i++){
if (nTimes == 0){
//初始化或重置candidate
candidate = ID[i];
nTimes++;
}
else
if (candidate == ID(i))
nTimes++;
else
nTimes--;
}
return candidate;
}
拓展:
删除不相同的4个数,剩下的ID即是我们所要找的。
void Find3(int * ID, int N)
{
int candidate[3] = { 0, 0, 0 };
int nTimes[3] = { 0, 0, 0 };
for (int i = 0; i<N; i++)
{
if (nTimes[0] == 0)
{
if (ID[i] == candidate[1])
nTimes[1]++;
if (ID[i] == candidate[2])
nTimes[2]++;
else
{
candidate[0] = ID[i];
nTimes[0]++;
}
}
if (nTimes[1] == 0)
{
if (ID[i] == candidate[0])
nTimes[0]++;
if (ID[i] == candidate[2])
nTimes[2]++;
else
{
candidate[1] = ID[i];
nTimes[1]++;
}
}
if (nTimes[2] == 0)
{
if (ID[i] == candidate[0])
nTimes[0]++;
if (ID[i] == candidate[1])
nTimes[1]++;
else
{
candidate[2] = ID[i];
nTimes[2]++;
}
}
else
{
if (ID[i] == candidate[0])
nTimes[0]++;
if (ID[i] == candidate[1])
nTimes[1]++;
if (ID[i] == candidate[2])
nTimes[2]++;
else
{
nTimes[0]--, nTimes[1]--, nTimes[2]--;
}
}
}
printf("ID分别为%d,%d,%d\n",candidate[0],candidate[1],candidate[2]);
}
心得:开始学习编程之美了,总想记录下来。
这个题目的拓展思维蛮不错可以拓展到找到n个的问题。