编程之美-2.3-寻找发帖“水王”

来源:互联网 发布:软件开发验收标准 编辑:程序博客网 时间:2024/05/16 12:56

题目:寻找一个ID列表中,有一个ID超过了总数的一半,找出这个ID

分析:

可以对ID进行排序,因为需要寻找的ID超过了一半,所以该ID列表ID[N]中,ID[N/2]一定是这个ID值。复杂度为O(NlgN+1),如果用排序这种方法解决的话,复杂度应该就维持在这个水平,不会降低。再思考一下,难道一定需要排序吗,针对这个问题,我们只是想找出ID数量超过一半的那个唯一的ID。如果每次删除两个不同的ID,那么数量超过一半的那个ID在剩下的ID列表中总会维持超过一半的数量,最后剩下的就一定是该ID。

/*寻找发帖水王,算法有些类似于寻找最大和子序列*/Type FInd(Type * ID, int N){    Type candicate;    int i, nTimes;  //nTimes用来记录重复次数    for(i = nTimes = 0; i < N; i ++){        if(nTimes == 0){            candicate = ID[i];                   //如果发现nTimes=0,则前面的重复完全抵消,重新选择一个candicate             nTimes = 1;        }else {            if(candicate == ID[i]) nTimes ++;    //如果发现相同ID,重复次数加1             else nTimes --;                      //否则减少         }    }    return candicate;}      

扩展问题:

“超级水王”没有了,有3个ID发帖也很多,每个人都超过帖子总数的1/4了,怎么快速找到这三个ID?

思路和“超级水王”的是一样的,只是这次需要有三个candicate[3],和三个nTimes[3]。如果找到与这三个ID相同的,则对应的加1,如果都不相同,则三个ID数量都要减1

/*寻找发帖水王,算法有些类似于寻找最大和子序列*/Type *Find(Type * ID, int N){    Type candicate[3];    int i, j, k, nTimes[3];  //nTimes用来记录重复次数    for(i = 0; i < 3; i++) nTimes[i] = 0;    for(i = 0; i < N; i ++){                for(j = 0; j < 3; j ++){            if(nTimes[j] == 0){                candicate[j] = ID[i];                   //如果发现nTimes=0,则前面的重复完全抵消,重新选择一个candicate                 nTimes[j] = 1;            }else {                if(candicate[j] == ID[i]) {                    nTimes[j] ++;    //如果发现相同ID,重复次数加1                     break;                }            }        }        //与这三个ID都不同,则都要减1         if(j == 3){           for(k = 0; k < 3; k++) nTimes[k]--;        }      }    return candicate;}


原创粉丝点击