查找之摩尔投票算法
对于一个一位数组array[1,5,1,3,2,3,3,3,4,9,6,4,3,3,3,3],找出其中超过数组中一半长度的数。今天学到了一种是摩尔投票算法。其他的一种算法是首先对数组进行排序,这样从小到大,并且超过一半,该数存在的话一定在数组的正中间。这样最后对该数进行检查一遍,因为有可能对于刚好是等于一半的数。
摩尔投票算法的思想是,首先定义一个majority和一个count,majority用来存放当前出现次数最多的数。如当majority等于第一个数后,count=1;然后majority与第二个数比较,如果相等,则count+1,否则count-1,如果减到count=0的时候,则说明该数在出现的当前序列已经不是出现次数最多的了,因此替换为当前的数。然后继续比较下去。最后同样要对得出来的数进行检验。
1 public static int getValue(int[] gifts, int n) { 3 int half=n/2; 5 int majority=0,count=0; 6 for(int i:gifts){ 7 if(count==0){ 8 majority=i; 9 count++; 10 } 11 else{ 12 if(majority!=i){ //当majority与当前数i不等时, 13 count--; //则计数count-1,如果count减一之后为0,则替换。 14 } 15 else{ 16 count++; 17 } 18 } 19 if(count>half){ 20 return majority; 21 } 22 } 23 count=0; 24 for(int i:gifts){ 25 if(majority==i){ 26 count++; 27 } 29 } 30 if(count>half){ 31 return majority; 32 } 33 else return 0; 34 }
从找到数组中超过1/2的数变换为找到1/3的数,可以知道,数组中超过1/2的数最多一个,1/3的最多两个。
1 public static String gettwomax(int[] a,int n){ 2 int m1=0,m2=0; 3 int c1=0,c2=0; 4 String maxTwoTimesNumber=""; 5 for(int i:a){ 6 if(m1==i){ 7 c1++; 8 } 9 else if(m2==i){ 10 c2++; 11 } 12 else if(c1==0){ 13 m1=i; 14 c1++; 15 } 16 else if(c2==0){ 17 m2=i; 18 c2++; 19 } 20 else{ 21 c1--; 22 c2--; 23 } 24 } 25 c1=0; 26 c2=0; 27 for(int i:a){ 28 if(i==m1){ 29 c1++; 30 } 31 if(i==m2){ 32 c2++; 33 } 34 } 35 if(c1>n/3){ 36 maxTwoTimesNumber+=m1; 37 } 38 if(c2>n/3){ 39 maxTwoTimesNumber+=m2; 40 } 41 return maxTwoTimesNumber; 42 43 }
同样对于大于n/3的数,我们需要两个数来记录。比如数组[a,b,a,b,c],首先各自m1,m2,计数为0,当一个个条件去比较时,m1=a,c1=1,m2=b,c2=2,然后i等于a,i==m1,所以c1加一,然后i=b,c2加一,然后i=c,条件都不符合,则c1,c2都各自减一。若后续计数为0时,则把当前的数替换为m1或m2.
jeyfang