2.3--寻找发帖水王
直接的方法是对所有的id进行排序,然后在扫描一遍ID列表,统计各个ID出现的次数。如果某个ID出现的次数超过一半,那么就输出这个ID这个算法的时间复杂度是O(N*logN+N)。
如果ID列表有序,则不需要扫描列表。如果一ID出现的次数超过总数的一半。那么无论水王的ID是什么,这个有序表的第N/2项 一定会是这个ID
以上两种方法都是先对ID列表进行排序,时间复杂度没有根本改进,能否避免排序?如果每次删除两个不同的ID,那么,在剩下的列表中,水王ID出现的次数仍然超过总数的一半。总的时间复杂度是O(N)。
int Find(int *ID,int N){//每次删除两个不同的id int candidate; for(int i=nTimes=0;i<N;++i){ if(nTimes==0){ candidate=ID[i]; nTimes=1; } else{ if(candidate==ID[i]){//id相同则累加,直到遇到不同的则-- nTimes++; } else nTimes--; } } return candidate; }
扩展问题:有3个发帖很多的ID,他们的发帖数目都超过了帖子总数目的1/4,你能从发帖列表中快速找出他们吗?
int Find(int *ID,int N){//每次删除两个不同的id int candidate1; int candidate2; int candidate3; int nTimes1,nTimes2,nTimes3; for(int i=nTimes=0;i<N;++i){ if(nTimes1==0){ candidate1=ID[i]; nTimes1=1; } else{ if(candidate1==ID[i]){//id相同则累加,直到遇到不同的则-- nTimes1++; } else{ if(nTimes2==0){ candidate2=ID[i]; nTimes2=1; } else{ if(candidate2==ID[i]){//id相同则累加,直到遇到不同的则-- nTimes2++; } else{ if(nTimes3==0){ candidate3=ID[i]; nTimes3=1; } else{ if(candidate3==ID[i]){//id相同则累加,直到遇到不同的则-- nTimes3++; } else{ nTimes1--; nTimes2--; nTimes3--; } } } } } } } }