摩尔投票法寻找众数

要求:输入一个整数数组,找出其中所有出现超过 n/2或者n/3 次的元素并返回。(众数未必存在)

摩尔投票法

摩尔投票法的基本思想是,在每一轮投票过程中,从数组中找出一对不同的元素,将其从数组中删除。这样不断的删除直到无法再进行投票,如果数组为空,则没有任何元素出现的次数超过该数组长度的一半。如果只存在一种元素,那么这个元素则可能为目标元素。

寻找数组中出现个数超过n/2的众数

首先来考虑最简单的情况,寻找个数大于n/2(下取整)的元素,如果存在这样的元素,那么有且只有一个,不能存在两个个数大于n/2个不同的元素,仅这两个元素个数加起来就大于n了。假设如果存在满足条件的众数,从数组中删去不相同的两个元素,不断重复,那么剩下的那个元素就是众数。最差的情况是每次删去的两个元素刚好是一个非众数和一个众数,如果删去的元素是两个非众数,那剩下众数个数相对变多,因为众数个数大于n/2,这样到最后剩下的元素就是众数(如果存在众数),因为他未必存在众数,因此对这个元素进行遍历,来确定其个数是否大于n/2。
举两个简单例子7个元素的数组,众数的个数至少是4,如{1,2,1,3,1,4,1},当遇见两个不同元素就删除,先删除{1,2},再删除{1,3},{1,4}。最后剩下元素1。如果是{1,2,3,4,1,1,1}最后会剩下{1,1,1}。如果是8个元素,众数个数至少为5个,非众数最多就为3个。
具体的算法如下,先用将数组第一个元素赋值给value,计数器初始化为0,遍历整个数组,先检查count1的值,如果为0就重置value的值,并置计数器为1,count1不为0的话,如果和value相等就加一,不等就减一。重复直到遍历结束,用计数器count2来计数数组中值为value的元素个数,来检查是否大于n/2.Java代码如下:


```java
import java.util.Scanner;
public class lookformass {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		 Scanner input = new Scanner(System.in);
		 int num = input.nextInt();
	     int[] arrary = new int[num];
	     for(int i = 0; i<num;i++) {
	    	 	arrary[i]= input.nextInt();
	        }
	     input.close();
	     int value= arrary[0];
	     int count1 = 0;
	     for(int i = 0 ; i< num;i++) {
	    	 if(count1==0) value = arrary[i];
	    	 if(arrary[i]==value) {
	    		 count1++;
	    	 }
	    	 else {
	    		 count1--;
	    	 }
	     }
	     int count2=0;
	     for(int i = 0 ; i< num;i++) {
	    	 if(arrary[i]==value) {
	    		 count2++;
	    	 }
	     }
	     if(count2*2>num)
	    	 System.out.print(value);
	     else 
	    	 System.out.print("你所输入的数据中没有众数");
	}
}


## 寻找数组中出现个数大于n/3的元素
当寻找所有出现次数大于n/3的元素,显然最多只能有两个众数,由两个元素可以类推过来,每次都删除3个不相同的元素,剩下的应该就是众数了。定义a和b来暂存元素,counta和countb为他们的计数器。先将a和b都暂存第一个元素,计数器均置0,遍历数组,先和a比较,如果相等,counta加一,如不等,和b比较,和b相等countb加一,如果均不满足,来看counta是否为0,如果为0,改变a的值,置counta为1,如果counta不为0,来检查countb的值,为0,就改变b的值置countb为1。以上均不满足就将a和b的计数器减一就行了。可以这样来理解,a和b存放是这两个众数,当遍历的元素和a相等,就投a一票,和b相等就投b一票,当计数器为0的时候,说明应该更换众数候选了,如果计数器都不为0,那么就将两个计数器都减一。这一部分代码是
int a=arrary[0], b = arrary[0], counta = 0, countb = 0;
        for(int i =0 ; inum||countb*3>num) {
	    	 System.out.println("众数为");
		     if(counta*3>num)
		    	 System.out.println(a);
		     if(countb*3>num)
		    	 System.out.println(b);
	     }
	     else 
	    	 System.out.print("该数组中没有众数");
	}
}





# 本题的其他解法
具体可以参照leetcode
169.求众数 https://leetcode-cn.com/problems/majority-element/
222.求众数2https://leetcode-cn.com/problems/majority-element-ii/







你可能感兴趣的:(摩尔投票法寻找众数)