数组——028数组中出现次数超过一半的数字

1,问题描述

数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

2,解题思路

(1)思路一:

遍历数组,统计每个元素出现的次数。思路简单,但是时间复杂度是O(n^2).

(2)思路二:阵地攻守。

  • 阵地攻守思想:先找出可能的目标元素,再统计该元素出现的次数。时间复杂度是O(n).
  • 第一个数字作为第一个士兵,守阵地;count = 1;
  • 遇到相同元素,count++;
  • 遇到不相同元素,即为敌人,同归于尽,count--;
  • 当遇到count为0的情况,又以新的i值作为守阵地的士兵.
  • 继续下去,到最后还留在阵地上的士兵,有可能是目标元素。
  • 验证该元素出现的次数是否满足要求(出现[1,1,2,2]或者[1,2,3,4]的情况不满足要求,所以需要验证一下).

3,源码

/**
* @author Manduner_TJU
* @version 创建时间:2019年4月8日下午3:24:13
*/
public class MoreThanHalfNum {
	public static void main(String[] args) {
		int[] a = {1,2,3,2,2,2,5,4,2};
		//int result = MoreThanHalfNum_Solution(a);
		int result = MoreThanHalfNum_Solution2(a);
		System.out.println(result);
	}
	
    //1,遍历数组,统计每个元素出现的次数。思路简单,但是时间复杂度是O(n^2).
	public static int MoreThanHalfNum_Solution(int [] array) {
    	int len = array.length;
    	if(len == 0) return 0;

    	int result=0;
        count=0;
    	for(int i=0;i<len;i++) {
    		if(count(array[i],array)*2 > len) {
    			result = array[i];
    			break;
    		}
    	}
		return result;
    }

	public static int count(int x, int[] array) {
		int num=0;
		for(int i=0;i<array.length;i++) {
			if(x==array[i]) {
				num++;
			}
		}
		
		return num;
	}
	
	/**2,阵地攻守思想:先找出可能的目标元素,再统计该元素出现的次数。时间复杂度是O(n).
	 * 第一个数字作为第一个士兵,守阵地;count = 1;
	 * 遇到相同元素,count++;
	 * 遇到不相同元素,即为敌人,同归于尽,count--;
	 * 当遇到count为0的情况,又以新的i值作为守阵地的士兵.
	 * 继续下去,到最后还留在阵地上的士兵,有可能是目标元素。
	 * 验证该元素出现的次数是否满足要求(出现[1,1,2,2]或者[1,2,3,4]的情况不满足要求).
	 * @param a
	 * @return
	 */
    public static int MoreThanHalfNum_Solution2(int[] a) {
    	int num = a[0];
    	int count = 1;
    	for(int i=1;i<a.length;i++) {
    		if(a[i]==num) count++;
    		else count--;
    		if(count==0) {
    			num = a[i];
    			count = 1;
    		}
    	}
    	
    	int result=0;
        count=0;
    	for(int i=0;i<a.length;i++) {
    		if(a[i]==num) count++;
    	}
    	
    	if(count*2>a.length) result = num;
        return result;
	}

	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值