问题
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。面试
例如: 输入一个长度为7的数组,数组
{1,2,2,2,5,4,2}
因为数字2在数组中出现了4次,超过数组长度的一半,所以输出2。若是不存在则输出0。spa
解答调试
首先说这是一道很经典的面试题,不少互联网公司都曾经采用过这个题目。code
下面是对该题的分析思路:排序
若是没有时间复杂度的要求, 咱们能够对数组进行排序,排序后的数组,那么咱们只要遍历一次就能够统计出每一个数字出现的次数,这样也就能找出符合要求的数字。按照这个思路的时间复杂度是O(nlogn), 其中排序的时间复杂度是O(nlogn),遍历的时间复杂度O(n)。字符串
另外一个思路是咱们能够建立一个哈希表来消除排序的时间。哈希表的键值为数组中的数字,值为该数字对应的次数。有了这个哈希表以后,咱们只须要遍历数组中的每一个数字,找到它在哈希表中对应的位置并增长它出现的次数。这种哈希表的方法在数组的全部数字都在一个比较窄的范围内的时候颇有效。get
最佳思路:数组中有一个数字出现的次数超过数组长度的一半,也就是说它出现的次数比其余全部数字出现次数的和还要多。
所以咱们能够考虑在遍历数组的时候保存两个值:一个是数组中的一个数字,一个是次数。当咱们遍历到下一个数字的时候,若是下一个数字和咱们以前保存的数字相同,则次数加1;若是下一个数字和咱们以前保存的数字不一样,则次数减1。
若是次数为0,咱们须要保存下一个数字,并把次数置1。由于次数为0,表示前面是字符串计数抵消为0。源码
//Java源码 public int MoreThanHalfNum_Solution(int [] numbers) { int maxNum = 0; if(numbers.length==0) return maxNum; maxNum = numbers[0]; int numCount = 1; for(int i=1;i<numbers.length-1;i++){ if(numbers[i] == maxNum){ numCount++; }else{ numCount--; if(numCount == 0){ numCount = 1; maxNum = numbers[i]; } } } int total = 0; for (int i = 0; i < numbers.length; i++) { if (numbers[i] == maxNum) total++; } if (total * 2 <= numbers.length) { return 0; } else return maxNum ; }
上述源码能够在 这里 调试io