O(n)复杂度,求数组中第2大的数

为什么我反对纯算法面试

提及一条算法题目,查找一个数组中第二大的数。

 

第二大数,直接想到的是,先遍历一次数组,把最大的取出来。然后再遍历一次,把最大的取出来。总耗费时间复杂度O(n + n -1)

还有没有其他O(n)的算法呢?

 

先挖坑,在填坑,都到凌晨2点了,明天想下

 

早上起来,想了下,跟上次连续子数组的思维差不多,用两个数字保存最大的两个数值,大的放前面,第二大的放后面,然后在遍历过程中穷举各种情况即可。

Java代码   收藏代码
  1. public class kmax{  
  2.     public static void main(String[] args){  
  3.         int[] a = new int[]{1,3,-2,32,-3,5};  
  4.         System.out.println(get2ndMax(a));  
  5.     }  
  6.     public static int get2ndMax(int[] a){  
  7.         //max[0]存放最大值,max[1]存放第二最大值  
  8.         int[] max = new int[2];  
  9.         if(a[0]>a[1]){  
  10.             max[0] = a[0];  
  11.             max[1] = a[1];  
  12.         }else{  
  13.             max[0] = a[1];  
  14.             max[1] = a[0];  
  15.         }  
  16.   
  17.         for(int i=2;i<a.length;i++){  
  18.             //穷举,其实就2种情况  
  19.             if(a[i]>max[0]){  
  20.                 max[1] = max[0];  
  21.                 max[0] = a[i];  
  22.             }else if(a[i]>max[1]){  
  23.                 max[1] = a[i];  
  24.             }  
  25.         }  
  26.         return max[1];  
  27.     }  
  28. }  

 


 去中大打完球回来,除了一身汗,把想到的位图方法也写上吧。编程珠玑中使用位图排序实现了O(n)的排 序,让我大开眼界,原来在特定条件下,O(n)排序也是可能的。既然O(N)的排序都有了,查找第2大的数字也没问题。假定数组的数字都是整数,上限是 MAX,下限是MIN。算法的复杂度是O(2*(MAX-MIN))。

 

Java代码   收藏代码
  1. public class BitmapKmax{  
  2.     public static void main(String[] args){  
  3.         int[] a = new int[]{-20,-29,32,99,29,10,39,42,28};  
  4.         System.out.println(get2ndMax(a,-100,100));  
  5.     }  
  6.       
  7.     public static int get2ndMax(int[] a, final int MIN, final int MAX){  
  8.         if(a.length<2){  
  9.             throw new IllegalArgumentException("array must contain at least 2 elements");  
  10.         }  
  11.         int secondMax = 0;  
  12.         byte[] byteArr = new byte[(MAX-MIN)/8 + 1];  
  13.         for (int i=0; i<a.length; i++) {  
  14.             int v = a[i]-MIN;  
  15.             int index = v/8;  
  16.             int v2 = v%8;  
  17.             byteArr[index] = (byte)(byteArr[index] | (1<<v2));  
  18.         }  
  19.         for (int i=0, count=0; i<byteArr.length; i++) {  
  20.             if(byteArr[i]!=0){  
  21.                 for(int j=0;j<8;j++){  
  22.                     if(0 != (byteArr[i] & (1<<j))){  
  23.                         count++;  
  24.                     }  
  25.                     if(2 == count){  
  26.                         secondMax = i*8 + j;  
  27.                         break;  
  28.                     }  
  29.                 }  
  30.                 if(2 == count){  
  31.                     break;  
  32.                 }  
  33.             }  
  34.         }  
  35.         return secondMax+MIN;  
  36.     }  
  37.       
  38. }  

 

至于他文章中所说的那个同学没有用O(n)的方法去做,而是用排序,我也挺佩服的。说实话,我也忘了O(nlogn)的快排怎么写了,呵呵,只记得用了分治递归的思想。嗯,下次我也尝试不看书的情况写个快排。

 

各位看官,不知道有没有其他方法,请不吝笔墨,大书特书。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值