寻找水王·扩展

来源:互联网 发布:淘宝助理怎么下架 编辑:程序博客网 时间:2024/05/16 08:48

        题目:随着Tango的发展,管理员发现,“超级水王”没有了。统计结果表明,有3个发帖很多的ID,他们的发帖数目都超过了帖子总数目N的1/4。你能从发帖ID列表中快速找出他们的ID吗?

      分析:编美里面寻找水王的方法已经说明白了,遍历一遍,每次减少两个元素,将原问题分解成更小规模的问题,这其中的原因是因为减少了问题规模之后原来“水王帖子的数量超过总数的一半”的特性依然存在。扩展的问题思路也是一样,根据题意,水王们的发帖数目一定会超过1/4,因此在后面写代码的时候不考虑找出水王之后验证合不合法。参考原问题的解法,可以知道:如果每次删除四个不同的ID,则在剩下的ID列表中,原先发帖比例大于1/4的ID所占比例仍然大于1/4。不断重复这个过程,最终得到答案。

      网上有很多直接在原问题的解法基础上,暴力遍历候选集candidates。在原问题的时候candidates只有一个,使用一个变量来保存就可以,在拓展问题中candidates有三个,因此需要用一个长度为3的数组来保存,另外用于计数candidates出现次数的标志也从原来的一个变量变成一个长度为3的数组。之所以说这种解法暴力,是大家的代码因为有很多if-else,把各种情况考虑周全了。这里转一份网上大神们的参考代码(转载地址,侵删。)

void Find(Type* ID, int N,Type candidate[3]){    Type ID_NULL;//定义一个不存在的ID    int nTimes[3], i;    nTimes[0]=nTimes[1]=nTimes[2]=0;    candidate[0]=candidate[1]=candidate[2]=ID_NULL;    for(i = 0; i < N; i++)    {        if(ID[i]==candidate[0])        {             nTimes[0]++;        }        else if(ID[i]==candidate[1])        {             nTimes[1]++;        }        else if(ID[i]==candidate[2])        {             nTimes[2]++;        }        else if(nTimes[0]==0)        {             nTimes[0]=1;             candidate[0]=ID[i];        }        else if(nTimes[1]==0)        {             nTimes[1]=1;             candidate[1]=ID[i];        }        else if(nTimes[2]==0)        {             nTimes[2]=1;             candidate[2]=ID[i];        }        else        {             nTimes[0]--;             nTimes[1]--;             nTimes[2]--;         }    }    return;}

        但是,我寻思着,如果不止3个水王呢?如果是4个水王,5个水王,甚至是更多水王?事实上1个水王的时候水贴超过一半,3个水王的时候每人水贴超过1/4,可以推出有n个水王,每人所占水贴超过1/(n+1),因此应该有个通用的思路来找出这些水王。下面是我自己实现,遍历帖子的每一个元素时:1)首先检查candidates中有没有出现过,如果出现过,将对应的计数器加1;2.1)如果全部没有出现过,则找到第一个计数器为0的位置,作为这个candidate的的位置,并把计数器加1;2.2)如果这些candidates的计数器全部不为0,以为着当前元素跟这n个水王候选都不一样,因此删去这(n+1)个人。相应的代码如下,为了便于测试,假设原数组中都是整数,因此可以用负数来初始化候选人数组。

void findKnums(int data[], int size) {if (data == NULL || size <= 0) return;int counts[NUM] = { 0 };int results[NUM] = { -1 };for (int i = 0; i < size; ++i) {bool isInK = false;bool hasZeroCount = false;for (int j = 0; j < NUM; ++j) {if (results[j] == data[i]) {counts[j]++;isInK = true;break;}}if (!isInK) {for (int j = 0; j < NUM; ++j) {if (0 == counts[j]) {results[j] = data[i];counts[j]++;hasZeroCount = true;break;}}if (!hasZeroCount) {for (int j = 0; j < NUM; ++j)counts[j]--;}}}for (int j = 0; j < NUM; ++j)cout << results[j] << " ";cout << endl;}


0 0
原创粉丝点击