看题目:算法
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为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; }