剑指offer之面试题29:数组中出现次数超过一半的数字
来源:互联网 发布:出入无时 莫知其乡解释 编辑:程序博客网 时间:2024/05/16 16:04
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路:
一般方法:先排序,然后统计每个数字出现的次数,O(nlogn)
其他方法:
数组中有一个数字出现的次数超过数组长度的一半,如果把这个数组排序,那么排序之后位于数字中间的数字一定就是要找的数,如果有的话,转化成中位数问题,即长度为n的数组中第n/2大的数字,有期望时间为线性的随机选择算法或者最坏时间为线性的k选择算法。
代码如下:
public class Solution { public static boolean g_InputInvalid=false; public static int MoreThanHalfNum_Solution(int [] array) { //数组长度超过一半,换种角度考虑就是,当数组有序时,该数应位于数组的中间 //后者其实就是中位数的定义,那原来的题目就变成找出数组的中位数(前提:并对该中位数计数,若超出数组长度一半时,才等价) //中位数的程序,算法导论中有讲到,利用partition函数随机化版本,可以在期望时间O(n)内找到,这种算法是原址的,不使用额外空间 if(array==null||array.length<=0){ g_InputInvalid=true; return 0; } int middle=array.length>>1;//位操作比除操作快,等价于array.length/2 int start=0; int end=array.length-1; int index=Partition(array,start,end); while(index!=middle){ if(index>middle){ end=index-1; index=Partition(array,start,end); } else{ start=index+1; index=Partition(array,start,end); } } int result=array[middle]; if(!CheckMoreThanHalf(array,result)){ result=0; } return result; } public static boolean CheckMoreThanHalf(int[] array, int result) { int times = 0; for (int i = 0; i < array.length; i++) { if(array[i] == result){ times++; } } boolean isMoreThanHalf = true; if(times * 2 <= array.length){ g_InputInvalid=true; isMoreThanHalf = false; } return isMoreThanHalf; } //O(n) public static int Partition(int[] array, int start, int end) { int k=(int)(Math.random()*(end - start + 1)) + start; swap(array,k,end); int x=array[end]; int i=start-1; for(int j=start;j<end;j++){ if(array[j]<=x){ i++; swap(array,i,j); } } swap(array,i+1,end); return i+1; } public static void swap(int[] array, int k, int end) { int temp=array[k]; array[k]=array[end]; array[end]=temp; } public static void main(String[] args){ int[] array = new int[]{1,2,3,2,2,2,5,4,2}; int a = MoreThanHalfNum_Solution(array); System.out.println(a); }}
另外一种解法,时间O(n)
数组中一个数字出现的次数超过数组长度的一半,说明出现的次数比其他数出现的次数之和还多。可以保存两个值,一个是数字,一个是次数。当遍历到一个数时,如果与前一个数相同,则times+1,如果不同times-1,当times=0时,将当前值保存,并将times设为1,当然这样只能排除不超过一半的,如果存在超过一半的只能是最后设为1的数,所以还要加个判断。
代码如下:
public class Solution { public static boolean g_InputInvalid=false; // not change array's element,cost is O(n) public static int MoreThanHalfNum_Solution(int[] array) { if(array==null||array.length<=0){ g_InputInvalid=true; return 0; } int result=array[0]; int times=1; for(int i=0;i<array.length;i++){ if(array[i]==result) times++; else times--; if(times==0){ result=array[i]; times=1; } } if(!CheckMoreThanHalf(array,result)){ result=0; } return result; } public static boolean CheckMoreThanHalf(int[] array, int result) { int times=0; for(int i=0;i<array.length;i++){ if(array[i]==result) times++; } boolean isMoreThanHalf=true; if(times*2<=array.length){ isMoreThanHalf=false; g_InputInvalid=true; } return isMoreThanHalf; } public static void main(String[] args){ int[] array=new int[]{1,2,3,2,2,2,5,4,2}; int result=MoreThanHalfNum_Solution(array); System.out.println(result); }}
0 0
- 剑指offer之面试题29:数组中出现次数超过一半的数字
- 剑指offer之面试题29数组中出现次数超过一半的数字
- 剑指Offer之面试题29:数组中出现次数超过一半的数字
- [剑指offer][面试题29]数组中出现次数超过一半的数字
- 剑指Offer:面试题29 数组中出现次数超过一半的数字
- 剑指offer 面试题29—数组中出现次数超过一半的数字
- 《剑指Offer》学习笔记--面试题29:数组中出现次数超过一半的数字
- 【剑指Offer学习】【面试题29 :数组中出现次数超过一半的数字】
- 剑指Offer面试题29(java版):数组中出现次数超过一半的数字
- 剑指offer面试题29-数组中出现次数超过一半的数字
- 剑指offer-面试题29:数组中出现次数超过一半的数字
- 剑指Offer----面试题29:数组中出现次数超过一半的数字
- 剑指offer-----面试题29(数组中出现次数超过一半的数字)
- 剑指Offer面试题29:数组中出现次数超过一半的数字 Java实现
- 剑指offer面试题29:数组中出现次数超过一半的数字
- 剑指offer--面试题29:数组中出现次数超过一半的数字
- 剑指Offer面试题29(java版):数组中出现次数超过一半的数字
- 剑指offer——面试题29:数组中出现次数超过一半的数字
- android 关于Button在StateListDrawable 中使用AnimationDrawable的问题
- 315. Count of Smaller Numbers After Self
- 数组的选择排序和冒泡排序
- Jetty启动
- 类与对象
- 剑指offer之面试题29:数组中出现次数超过一半的数字
- More Effective C++----(11)禁止异常信息传递到析构函数外
- c++ 内存分区
- 百度地图API之覆盖物和事件
- 有理有条地绘制立体图(利用数据结构)
- 关于javascript的seal的扩展性一
- iPhone手机数据提取分析(一)
- oracle dba create view 失败 解决办法
- Postgresql 9 管理 手册(第二版)