面试题29数组中出线次数超过一半的数字

//==========================以下为自己实现==============

O(n) 的解法,也可以从头到尾遍历,两个遍历,val, count

相等count++

不相等count--

count==0时候,更新val为当前遍历的数

最后剩余的那个val,就是count大于一半的数


另外:当有2个数超过1/3的时候,同理,设置val1,count1, val2 count2,从头到尾遍历一遍即可。

//==========================以下为转载=================

https://blog.csdn.net/u010425776/article/details/50907362

题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。


分析:本题最直观的思路就是分别统计数组中每个数出现的次数,然后求出最大值,判断是否超过数组长度的一半。这种方法的时间复杂度为O(n^2),在面试中,第一反应想到的方法往往不是最佳答案,下面我们来寻求更加高效的方式。


一个数出现的次数如果超过数组长度的一半,那么可以得出以下结论:

1.如果把超过数组长度一半的数整理在一起形成数组b,那么不管把b放在数组的什么位置,数组的中位数一定在b中。

2.个数超过数组长度一半的数最多只有一个。

基于上述两点结论,我们可以首先将数组排序,使得超过数组长度一半的那些数靠在一起,然后取排序后数组的中位数,最后判断该数的长度是否超过数组长度的一半。代码如下:

  1. import offer8.QuickSort;
  2. /**
  3. * 题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
  4. * @author 大闲人柴毛毛
  5. * @date 2016年3月16日
  6. */
  7. public class CountNumber {
  8. /**
  9. * 分析:本题最直观的思路就是分别统计数组中每个数出现的次数,然后求出最大值,判断是否超过数组长度的一半。
  10. * 这种方法的时间复杂度为O(n^2),在面试中,第一反应想到的方法往往不是最佳答案,下面我们来寻求更加高效的方式。
  11. */
  12. /**
  13. * 一个数出现的次数如果超过数组长度的一半,那么可以得出以下结论:
  14. * 1.如果把超过数组长度一半的数整理在一起形成数组b,那么不管把b放在数组的什么位置,数组的中位数一定在b中。
  15. * 2.个数超过数组长度一半的数最多只有一个。
  16. * 基于上述两点结论,我们可以首先将数组排序,使得超过数组长度一半的那些数靠在一起,然后取排序后数组的中位数,最后判断该数的长度是否超过数组长度的一半。
  17. * 代码如下:
  18. */
  19. /**
  20. * 获取数组中出现次数超过一半的那个数
  21. * @param a 输入的数组
  22. * @return 返回出现次数超过一半的那个数(返回-1表示函数出错)
  23. */
  24. public static int countNumber(int[] a){
  25. //若数组为空
  26. if(a== null || a.length<= 0){
  27. System.out.println( "数组为空!");
  28. return - 1;
  29. }
  30. //对数组排序
  31. QuickSort.QuickSort(a);
  32. //获取中位数
  33. int mid = a[a.length/ 2];
  34. //计算中位数出现的次数
  35. int count = 0;
  36. for( int i= 0;i<a.length && a[i]<=mid;i++){
  37. if(a[i]==mid)
  38. count++;
  39. }
  40. //判断中位数出现的次数是否超过数组长度的一半
  41. if(count>=a.length/ 2)
  42. return mid;
  43. else
  44. return - 1;
  45. }
  46. /**
  47. * 测试
  48. */
  49. public static void main(String[] args){
  50. int[] a = { 3, 1, 3, 2, 3, 2, 3, 2, 2, 3, 5, 3, 4, 2, 3, 3};
  51. System.out.println(countNumber(a));
  52. }
  53. }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值