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

为什么我反对纯算法面试

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

 

第二大数,直接想到的是,先遍历一次数组,把最大的取出来。然后再遍历一次,把最大的取出来。总耗费时间复杂度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)的快排怎么写了,呵呵,只记得用了分治递归的思想。嗯,下次我也尝试不看书的情况写个快排。

 

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

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值