看題目:算法
數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字。例如輸入一個長度爲9的數組{1,2,3,2,2,2,5,4,2}。因爲數字2在數組中出現了5次,超過數組長度的一半,所以輸出2。若是不存在則輸出0。數組
個人直接思路:函數
用map計數,簡單直接,遍歷一次數組,用hashmap記錄,key爲int值,value爲出現次數;spa
第二次再用map.entrySet找出有沒value大於數組長度通常的entry,有的話返回它的key。code
時間複雜度也是2n而已,這個方法時間複雜度是O(n)空間複雜度也是O(n)blog
代碼實現:排序
/*方法1 蠻力,遍歷一次,用一個map來記錄 第二次遍歷把出現次數大於length/2的那個值找出來 */ public int MoreThanHalfNum_Solution(int [] array) { int targetCount = array.length / 2; //key爲數組中的值,value爲出現的次數 HashMap<Integer,Integer> map = new HashMap<Integer,Integer>(); for(int temp : array) { if(map.get(temp) == null)map.put(temp, 1); else map.put(temp, map.get(temp) + 1); } Set<Entry<Integer,Integer>> entrySet = map.entrySet(); for(Entry<Integer,Integer> entry : entrySet) { if(entry.getValue() > targetCount)return entry.getKey(); } return 0; }
方法2:中位數get
/*方法2 排序後中位數法 若是有個數字出現的次數大於數組長度的一半,那麼這個數組排序後,它的中位數必定是這個數字 */ public int MoreThanHalfNum_Solution(int [] array) { Arrays.sort(array); int count = 0, middleNum = array[array.length / 2]; for(int temp : array) { if(temp == middleNum)count++; } if(count > array.length / 2)return middleNum; else return 0; }
方法3:——快排思路hash
方法2中,咱們排序是爲了找出中位數,那麼若是能夠更快地找出中位數就不用排序了。it
/*方法3 利用快排的思想 */ public int MoreThanHalfNum_Solution(int [] array) { if(array.length <= 0)return 0; int begin = 0, end = array.length - 1, middle = array.length / 2; int partition = partition(array, begin, end); while(partition != middle) { if(partition > middle) {//中位數在partition的左邊 partition = partition(array, begin, partition - 1); } else {//中位數在partition右邊 partition = partition(array, partition + 1, end); } } //找出中位數了,看這個中位數出現的次數是否符合要求 int count = 0, middleKey = array[middle]; for(int temp : array) { if(temp == middleKey)count++; } if(count > array.length / 2)return array[middle]; else return 0; } //這個方法是以第一個元素爲基準,而後進行劃分,劃分後比基準元素小的數字都在它左邊,比它大的數字都在它右邊 返回劃分後,這個元素的新index// private int partition(int[] a, int begin, int end) { int key = a[begin]; int i = begin, j = end; while(i < j) { while(i < j && a[j] >= key)j--; while(i < j && a[i] <= key)i++; swap(a, i, j); } swap(a, begin, i); return i; } //交換數字函數,傳入數組還有要交換的兩個數字的index// private void swap(int[] a, int first, int second) { int temp = a[first]; a[first] = a[second]; a[second] = temp; }
當咱們遍歷到下一個數字的時候,
若是下一個數字和當前咱們保存的數字相同,則次數加 1;
若是和當前咱們保存的數字不一樣,則次數減 1;
當次數減到 0 的時候,咱們將保存的數字改成當前遍歷所處的位置,並將次數更改成 1。
看代碼:
/*方法4 陣地攻守思想,其實和牛客上面那個什麼「用戶分形葉」的思路同樣的,不一樣實現而已 */ public int MoreThanHalfNum_Solution(int [] array) { int count = 1, key = array[0]; for(int temp : array) { if(temp == key)count++; else if(count > 0)count--; else { key = temp; count = 0; } } //判斷這個獲得的key是否是符合要求 int count2 = 0; for(int temp : array) { if(temp == key)count2++; } if(count2 > array.length / 2)return key; else return 0; }