LetCode1560 (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]. 摩爾投票

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章