LetCode-1560 (Offer29) - 数组中出现次数超过一半的数字

前言

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

测试数据组:

Case1: {1,2,3,2,2,2,5,4,2}
Result: 2

Case2: {1,2,3,2,4,2,5,2,3}
Result: 0

Case3: {}
Result: 0

Case 4:{1}
Result: 1

Case 5:{1,2}
Result: 0

解法与思路

  • IDEAL 1 排序再查中间值
    先进行简单快速排序. 随后找到中间值. 再进行一轮的Check. 判断其Count数是否大于length/2.
    优化点: length>>1. 使用移位运算. 移位置运算需要注意+0-0的情况.

  • IDEAL 2 使用HashMap作为辅助空间
    将数字作为key, 个数作为value. 存储进入HashMap. 值得注意的是, 不需要使用TreeMap. 因为使用TreeMap你也无法获取有序的序列. 因为其根据key进行排序的.

  • IDEAL 3 摩尔投票
    在这里插入图片描述
    使用其方法需要注意的是.最后结束的时候还是需要进行判断一下.
    市面上的题解没有Case3. 使用Case 3, 会发现最后计算出为3. 其非中值. 是错误实例.


相关代码

package com.yanxml.algorithm.offer2.array;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.junit.Assert;
import org.junit.Test;

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

	// 方法1 - 快排.
    public int moreThanHalfNum_Solution(int [] array) {
    	int result = 0;
    	if(null != array) {
    		if(array.length==1) {result=array[0];}
    		if(array.length==2) {result=(array[0]==array[1]?array[0]:0);}
    		else if(array.length>2) {
    			int halfIndex = array.length>>1;
    			int start=0;
    			int end = array.length-1;
    			int index = quickSortPartition(array,start,end);
    			while(index != halfIndex) {
    				if(index>halfIndex) {
    					end = index-1;
    					index = quickSortPartition(array, start, end);
    				}else {
    					start = index+1;
    					index = quickSortPartition(array, start, end);
    				}
    	    		SortUtil.printArray(array);
    			}
    			// 判断index位置是否是中值位置.
    			if(checkIndexHalfOrNot(array,array[index])) {
    				result = array[halfIndex];
    			}
    		}
    		SortUtil.printArray(array);
    	}
        return result;
    }
    
    public boolean checkIndexHalfOrNot(int[] array,int indexNum) {
    	if(null!=array) {
    		int count = 0;
    		for(int i=0;i<array.length;i++) {
    			if(array[i]==indexNum) {
    				count++;
    			}
    		}
    		if(count>array.length>>1) {
    			return true;
    		}
    	}
    	return false;
    }
    
    public int quickSortPartition(int array[],int begin,int end) {
    	if(end<begin) {return -1;}
    	if(end==begin) {return begin;}
    	int frontIndex = begin;
		int endIndex = end;
		// 进行一轮快排序
		while(frontIndex<endIndex) {
			int guard = array[begin]; frontIndex++;
			while(array[endIndex]>=guard&& frontIndex<endIndex) {
				endIndex--;
			}
			while(array[frontIndex]<guard && frontIndex<endIndex) {
				frontIndex++;
			}
			SortUtil.swapAAndB(array,frontIndex,endIndex);
		}
		SortUtil.swapAAndB(array, begin, frontIndex);
		return frontIndex;
    }
    
    // 方法2-HashMap
    public int moreThanHalfNum_Solution_2(int [] array) {
    	int result = 0;
    	if(null !=array && array.length>0) {
    		// 写入TreeMap
        	Map<Integer,Integer> map = new HashMap<Integer, Integer>();
        	for(int i=0;i<array.length;i++) {
        		if(null != map.get(array[i])) {
        			map.put(array[i], map.get(array[i])+1);
        		}else {
        			map.put(array[i], 1);
        		}
        	}
        	// getFirst 判断
        	for(Entry<Integer, Integer> entry:map.entrySet()) {
        		if(entry.getValue() >= ((array.length+1)/2)) {
        			result = entry.getKey();
            		break;
        		}
        	}
    	}
    	return result;
    }
    
    // 方法3 - 使用临时空间k
    public int moreThanHalfNum_Solution_3(int [] array) {
    	int result =0;
    	if(null != array && array.length>0) {
    		int key=array[0];
        	int value=1;
        	for(int i=1;i<array.length;i++) {
        		if(value==0) {
        			key=array[i];
        			value =1;
        		}else {
        			if(array[i]==key) {
            			value++;
            		}else {
            			value--;
            		}	
        		}
        	}
        	// 判断范围值.
        	if(checkIndexHalfOrNot(array,key)) {
        		result = key;
        	}
        	// 错误做法.
//        	if(value>0) {
//        		result = key;
//        	}
    	}
    	return result;
    }
    
    //@Test
    public void testCase1(){
    	int []array={1,2,3,2,2,2,5,4,2};
    	int result = new MoreThanHalfOfArray().moreThanHalfNum_Solution(array);
    	//int result = new MoreThanHalfOfArray().moreThanHalfNum_Solution_2(array);
    	//int result = new MoreThanHalfOfArray().moreThanHalfNum_Solution_3(array);
    	Assert.assertEquals(result, 2);
    }
    
   // @Test
    public void testCase3() {
    	int []array= {1,2,3,2,4,2,5,2,3};
    	int result1 = new MoreThanHalfOfArray().moreThanHalfNum_Solution_2(array);
    	Assert.assertEquals(result1, 0);
    	int result2 = new MoreThanHalfOfArray().moreThanHalfNum_Solution_2(array);
    	Assert.assertEquals(result2, 0);
    	int result3 = new MoreThanHalfOfArray().moreThanHalfNum_Solution_3(array);
    	Assert.assertEquals(result3, 0);

    }
    
    @Test
    public void testMoveNumber() {
    	int i=1;
    	System.out.println(i>>1);
    }
}

Reference

[1]. LetCode 解析
[2]. 摩尔投票

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值