这个问题,解法比较多,先说下普通的想法,先设定最大值和最小值都为序列中第一个元素值,在一个循环内,每次循环都和当前最大值和最小值来比较更新,这样就需要2N-2次比较了;
再进一步,如果先查找最大值,则需N-1次比较,再查找最小值,则需N-2次比较,总共是2N-3次比较,比上一方法少了1次。
这些做法都是每次取1个数来比较,比较次数为O(2N)。接下来,我们把情况扩展到每次取多于1个数,先试试看每次取2个数,即N-2个数的解,对N个数求解。当N=1时,最大值和最小值就是第1个元素值;当N=2时,最大值和最小值就是第1个元素和第2个元素的最大值和最小值;考察X[N-2]和X[N-1],同时令前N-2个数的解是MAX和MIN,易见,做3次比较便能得出新的最大值和最小值,首先比较X[N-2]和X[N-1],然后将其中大数同MAX比较,小数同MIN比较,这样一来,大约需O(3N/2)次比较即可,而不是先前的O(2N)次。那么,是不是每次取3个或4个数能更进一步减少总共的比较次数呢?可以证明,每次取多于2个数来比较时,总共所需次数和取2个元素来比较是一样的。
这是用java实现的每次取两个元素的算法,代码如下。。
package test;
public class Get_max_min {
public static void main(String[] args) {
int[] jishu = new int[] { 9, 10, 44, 22, 53, 10, 23, 56, 77, 16, 60 };//测试奇数个数
int[] oushu = new int[] { 10, 44, 22, 53, 10, 23, 56, 77, 16, 60 };//测试偶数个数
int[] a = get_max_min(jishu);
int[] b = get_max_min(oushu);
System.out.println("奇数个,min:" + a[0] + ",max:" + a[1] + ",total:"
+ jishu.length + ",times:" + a[2]);
System.out.println("偶数个,min:" + b[0] + ",max:" + b[1] + ",total:"
+ oushu.length + ",times:" + b[2]);
}
/**查找序列(数组)中的最大值,最小值,
* param int[],要查找的序列
* return int[],返回这两个值和查找的次数组成的数组
*/
public static int[] get_max_min(int[] a) {
int[] result = new int[3];
int n = a.length;
int tmax, tmin, i, count = 0;
result[0] = result[1] = a[0];
for (i = 1; i < n - 1; i += 2) {
if (a[i] < a[i + 1]) {
tmax = a[i + 1];
tmin = a[i];
} else {
tmin = a[i + 1];
tmax = a[i];
}
count += 3;
if (result[0] > tmin)
result[0] = tmin;
if (result[1] < tmax)
result[1] = tmax;
}
if (i == n - 1) {
count += 2;
if (result[0] > a[n - 1])
result[0] = a[n - 1];
if (result[1] < a[n - 1])
result[1] = a[n - 1];
}
result[2] = count;
return result;
}
}
执行后结果如下:
由前面分析可知,当N为奇数时,总共比较次数为3/2*(N-1);当N为偶数时,总共比较次数为3N/2-1,时间复杂度为0(3N/2)。