分析1:对于给定数组找出其中最大的两个数,很容易想到的就是遍历数组。首先遍历整个数组,找出最大的一个元素并记录下该位置;然后分别遍历该位置之前的区间和该位置之后的区间,分别找出这两个子区间的最大值,然后比较这两个子区间的最大值,大者即为整个数组的次大元素。显然,整个过程中,用到了三次for循环,算法的时间复杂度是比较大的,对于规模较小的数组尚且可以,但是当问题的规模非常大时,这种遍历的方法就不可行了。
分析2:设置两个指针,分别指向数组的最大值和次大值(初始化时指向数组的前两个元素)。此后遍历数组的所有元素,每个元素都与这两个指针所指元素进行比较,到最后就能确定最大值和次大值。但是复杂度与第一种方法不相上下。
分析3:递归+分治的方法。
递归:分别找出左右两个区间的最大值与次大值,然后通过比较这四个值的大小,确定整个数组的最大值与次大值。
递归基:区间元素为两个或三个的情况。
下面给出代码:
// 找出给定数组中最大的两个数
#include <iostream>
using namespace std;
void max2(int A[], int lo, int hi, int& x1, int& x2);
int main()
{
int A[10] = {8, 3, 30, 25, 10, 22, 31, 35, 21, 19};
int x1 = 0;
int x2 = 0;
max2(A, 0, 9, x1, x2);
cout << "x1 = " << x1 << endl;
cout << "x2 = " << x2 << endl;
return 0;
}
void max2(int A[], int lo, int hi, int& x1, int& x2){
//x1存放最大的一个元素,x2存放次大的元素
//只有两个元素的情况
if(lo + 1 == hi){
if(A[lo] >= A[hi]){
x1 = A[lo];
x2 = A[hi];
return;
}
else{
x1 = A[hi];
x2 = A[lo];
return;
}
}
//只有三个元素的情况
if(lo + 2 == hi){
if(A[lo] >= A[lo+1]){
x1 = A[lo];
x2 = A[lo+1];
if(A[hi] > x2)
if(A[hi] > x1){
x2 = x1;
x1 = A[hi];
return;
}
else{
x2 = A[hi];
return;
}
}
else{
x1 = A[lo+1];
x2 = A[lo];
if(A[hi] > x2)
if(A[hi] > x1){
x2 = x1;
x1 = A[hi];
return;
}
else{
x1 = A[hi];
return;
}
}
}
//有四个及以上的元素就可以通过分治递归的方式划分成上面两种情况
int mi = (lo+hi) / 2;
//分别计算左右两个区间的最大的两个数
int x1L, x2L, x1R, x2R;
max2(A, lo, mi, x1L, x2L);
max2(A, mi+1, hi, x1R, x2R);
if(x1L >= x1R){
x1 = x1L;
x2 = x2L > x1R ? x2L : x1R;
return;
}
else{
x1 = x1R;
x2 = x1L > x2R ? x1L : x2R;
return;
}
}