算法之寻找多元数
package cn.dlb.bim.action; /* 定义:序列中的多数元素是指在一个元素个数为n的序列中,多数元素出现次数大于[n/2]. 如题目: 在序列1,3,3,2,3,3,4,3,中3是是多数元素,如何计算出他是多数元素呢? 寻找元素方法很多: 1.可以暴力搜索,将每个元素都与其他元素作比较,然后统计该元素出现的次数,时间复杂度为O(n2); 2.可以先排序,然后再统计每个元素出现的次数,时间复杂度为O(nlogn); 3.可以寻找中间值元素,因为多数元素在序列中必为中间值元素,时间复杂度是O(n);(寻找中间值元素可以运用寻找第k小元素算法:http://www.cnblogs.com/7hat/p/3411756.html) 这里要介绍第4种方法,时间复杂度也是O(n),但是隐藏常数会比寻找中间值的方法要小。 算法基于以下观察:在原序列中去除两个不同的元素后,那么在原序列中的多数元素在新序列中还是多数元素。 算法基本思路: (1)在寻找多数元素的过程中,将计数器置1,遇到相同元素则计数器加1,遇到不同元素则计数器减1,一直到计数器等于0或遍历完整个序列。由此可见,计数器的值表示当前元素抵消掉不同元素后的出现次数; (2)当计数器在遍历完整个序列前就已经是0,则忽略掉已经遍历过的元素(可以看作两两抵消 不影响序列中的多数元素),跳到下一个元素然后计数器重新置1,重复上述步骤,一直到遍历完整个元素; (3)当遍历完整个序列后,算法会返回一个值,此时我们还需要检测一次这 个值是否真的是多数元素,即遍历统计一次。这一步不可或缺。因为上述两 个步骤到了遍历完序列后必将返回一个值,无论序列有无多数元素。此值存 在三种情况,第一,它真的是多数元素;第二,它只是序列后面的某个元素 刚好抵消完序列;第三,两者皆是。我们必须检测一次。 * */ public class Duoshu { private static boolean flag; private static int candidate(int k, int[] A){ //find the candidate may be a majority int i = k; int x = A[k]; int count = 1; //indicates the current element occurrences, after offset different elements while(i < A.length-1 && count > 0){ //remove two different elements, the majority element will not change i ++; if(A[i] == x){ count ++; } else{ count --; } } //there are three cases of x: x is the majority element or x is the last element or both if(i == A.length-1)return x; return candidate(i+1, A); } public static int findMajority(int[] A){ //find the majority int x = candidate(0, A); int count = 0; for(int i = 0; i < A.length; i ++){ //Test whether x is really the majority of elements in the array if(A[i] == x){ count ++; } } if(count > A.length/2){ flag = true; return x; } else{ flag = false; return 0; } } public static int findMajority1(int[] A){ //Iteration int x = 0; for(int i = 0; i < A.length; i ++){ int count = 1; x = A[i]; while(i < A.length-1 && count > 0){ i ++; if(A[i] == x){ count ++; } else{ count --; } } } int count = 0; for(int i = 0; i < A.length; i ++){ if(A[i] == x)count ++; } if(count > A.length/2){ flag = true; return x; } else{ flag = false; return 0; } } public static void main(String[] args){ int[] A = {2, 3, 2, 4, 2}; int x1 = findMajority(A); if(flag){ System.out.println("Found it: " + x1); } else{ System.out.println("Not found!"); } int x2 = findMajority1(A); if(flag){ System.out.println("Found it: " + x2); } else{ System.out.println("Not found!"); } } }