题目描述
给定数组A[0…n-1],试设计一个算法,在最坏情况下用n+logn次比较找出A[0…n-1]中元素的最大值和次大值。
比较次数为2n的算法实现
public static int[] findSecondFirst(int[] array) {
int[] result=new int[2];
int max=array[0]>array[1]?array[0]:array[1];
int secondMax=array[0]>array[1]?array[1]:array[0];
if(array[0]>array[1]) {
max=array[0];
secondMax=array[1];
}else {
max=array[1];
secondMax=array[0];
}
for(int i=2;i<array.length;i++) {
if(array[i]>max) {
secondMax=max;
max=array[i];
}else if(array[i]>secondMax) {
secondMax=array[i];
}
}
result[0]=secondMax;
result[1]=max;
return result;
}
比较次数为n+lgn的算法
算法思想
- 采用分治法将数组A[0:n]分成两部分,A[0:n/2-1]和A[n/2:n-1]
- 对于第一部分,i=0到n/2-1,如果A[i]>A[i+n/2],就交换A[i]和A[i+n/2]
- 数组A[n/2:n-1]的大小>2,则按照步骤2进行递归分治求出最大值和最小值;如果大小<=2,则直接求出最大值和次最大值。假设最大值为A[p],次最大值为A[p]
- 原问题的最大值为A[p],次最大值为A[p-n/2]和A[q]的较大者。
算法实现
public static void search(int[] a,int[] result,int left,int right) {
if(left==right) {
result[0]=result[1]=left;
}else if(left==right-1) {
if(a[left]>a[right]) {
result[1]=left;
result[0]=right;
}else {
result[1]=right;
result[0]=left;
}
}else {
int m=(right-left+1)/2;
for(int i=left;i<left+m;i++) {
if(a[i]>a[i+m]) {
int temp=a[i];
a[i]=a[i+m];
a[i+m]=temp;
}
}
search(a,result,left+m,right);
if(a[result[1]-m]>a[result[0]]) result[0]=result[1]-m;
}
}
测试结果
参考
百度文库-算法与设计