提及一条算法题目,查找一个数组中第二大的数。
第二大数,直接想到的是,先遍历一次数组,把最大的取出来。然后再遍历一次,把最大的取出来。总耗费时间复杂度O(n + n -1)
还有没有其他O(n)的算法呢?
先挖坑,在填坑,都到凌晨2点了,明天想下
早上起来,想了下,跟上次连续子数组的思维差不多,用两个数字保存最大的两个数值,大的放前面,第二大的放后面,然后在遍历过程中穷举各种情况即可。
- public class kmax{
- public static void main(String[] args){
- int[] a = new int[]{1,3,-2,32,-3,5};
- System.out.println(get2ndMax(a));
- }
- public static int get2ndMax(int[] a){
- //max[0]存放最大值,max[1]存放第二最大值
- int[] max = new int[2];
- if(a[0]>a[1]){
- max[0] = a[0];
- max[1] = a[1];
- }else{
- max[0] = a[1];
- max[1] = a[0];
- }
- for(int i=2;i<a.length;i++){
- //穷举,其实就2种情况
- if(a[i]>max[0]){
- max[1] = max[0];
- max[0] = a[i];
- }else if(a[i]>max[1]){
- max[1] = a[i];
- }
- }
- return max[1];
- }
- }
去中大打完球回来,除了一身汗,把想到的位图方法也写上吧。编程珠玑中使用位图排序实现了O(n)的排 序,让我大开眼界,原来在特定条件下,O(n)排序也是可能的。既然O(N)的排序都有了,查找第2大的数字也没问题。假定数组的数字都是整数,上限是 MAX,下限是MIN。算法的复杂度是O(2*(MAX-MIN))。
- public class BitmapKmax{
- public static void main(String[] args){
- int[] a = new int[]{-20,-29,32,99,29,10,39,42,28};
- System.out.println(get2ndMax(a,-100,100));
- }
- public static int get2ndMax(int[] a, final int MIN, final int MAX){
- if(a.length<2){
- throw new IllegalArgumentException("array must contain at least 2 elements");
- }
- int secondMax = 0;
- byte[] byteArr = new byte[(MAX-MIN)/8 + 1];
- for (int i=0; i<a.length; i++) {
- int v = a[i]-MIN;
- int index = v/8;
- int v2 = v%8;
- byteArr[index] = (byte)(byteArr[index] | (1<<v2));
- }
- for (int i=0, count=0; i<byteArr.length; i++) {
- if(byteArr[i]!=0){
- for(int j=0;j<8;j++){
- if(0 != (byteArr[i] & (1<<j))){
- count++;
- }
- if(2 == count){
- secondMax = i*8 + j;
- break;
- }
- }
- if(2 == count){
- break;
- }
- }
- }
- return secondMax+MIN;
- }
- }
至于他文章中所说的那个同学没有用O(n)的方法去做,而是用排序,我也挺佩服的。说实话,我也忘了O(nlogn)的快排怎么写了,呵呵,只记得用了分治递归的思想。嗯,下次我也尝试不看书的情况写个快排。
各位看官,不知道有没有其他方法,请不吝笔墨,大书特书。