寻找数组中 的最大值最小值

时间:2023-01-12 15:14:21

最简单的方法就是N中的每个数分别和max,min比较,看似2N次比较,其实大于max的就不必和min比较,小于min的也不必和max比较,因此比较的次数不足2N次,程序如下:

[cpp] view plaincopy

  1. bool MaxMin(std::vector<T> array, T* max, T* min) {  
  2.   if (array.size() < 1) {  
  3.     return false;  
  4.   }  
  5.   *max = array[0];  
  6.   *min = array[0];  
  7.   size_t array_size = array.size();  
  8.   for (int i = 1; i < array_size; ++i) {  
  9.     if (array[i] > *max) {  
  10. 10.       *max = array[i];  
  11. 11.     } else if (array[i] < *min) {  
  12. 12.       *min = array[i];  
  13. 13.     }  
  14. 14.   }  
  15. 15.   return true;  

16. }  


其次方法是数组中的一对一对的数相互比较,比较中较大的一个和max比较,较小的和min比较,总计有N/2对数,分别和max和min进行一次比较,共计3N/2次比较,程序代码如下:

[cpp] view plaincopy

  1. template<typename T>  
  2. bool MaxMin_1(std::vector<T> array, T* max, T* min) {  
  3.   if (array.size() < 1) {  
  4.     return false;  
  5.   }  
  6.   *max = array[0];  
  7.   *min = array[0];  
  8.   int index = 1;  
  9.   int array_size = array.size();  
  10. 10.   while(index < array_size && index +1 <array_size) {  
  11. 11.     if (array[index] >= array[index + 1]) {  
  12. 12.       if (array[index] > *max) {  
  13. 13.         *max = array[index];  
  14. 14.       }  
  15. 15.       if (array[index + 1] < *min) {  
  16. 16.         *min = array[index + 1];  
  17. 17.       }  
  18. 18.     } else {  
  19. 19.       if (array[index + 1] > *max) {  
  20. 20.         *max = array[index + 1];  
  21. 21.       }  
  22. 22.       if (array[index] < *min) {  
  23. 23.         *min = array[index];  
  24. 24.       }  
  25. 25.     }  
  26. 26.     index += 2;  
  27. 27.   }   
  28. 28.   if (index < array.size()) {  
  29. 29.     if (array[index] > *max) {  
  30. 30.       *max = array[index];  
  31. 31.     }  
  32. 32.     if (array[index] < *min) {  
  33. 33.       *min = array[index];  
  34. 34.     }  
  35. 35.   }  
  36. 36.   return true;  

37. }  


最后一种方法是分治法,比较次数也是3N/2,程序如下:

[cpp] view plaincopy

  1. template<typename T>  
  2. bool MaxMin_2(std::vector<T> array, int start, int end, T* max, T* min) {  
  3.   if (end - start > 1) {  
  4.     MaxMin_2(array, start, (start + end) / 2, max, min);  
  5.     MaxMin_2(array, (start + end) / 2 + 1, end, max, min);  
  6.   } else {  
  7.     if (array[end] > array[start]) {  
  8.       if (array[end] > *max) {  
  9.         *max = array[end];  
  10. 10.       }  
  11. 11.       if (array[start] < *min) {  
  12. 12.           *min = array[start];  
  13. 13.       }  
  14. 14.     } else {  
  15. 15.       if (array[start] > *max) {  
  16. 16.         *max = array[start];  
  17. 17.       }  
  18. 18.       if (array[end] < *min) {  
  19. 19.         *min = array[end];  
  20. 20.       }  
  21. 21.     }  
  22. 22.   }  

23. }  

24. template<typename T>  

25. bool MaxMin_3(std::vector<T> array, int start, int end, T* max, T* min) {  

  1. 26.   if (end > start) {  
  2. 27.     MaxMin_2(array, start, (start + end) / 2, max, min);  
  3. 28.     MaxMin_2(array, (start + end) / 2 + 1, end, max, min);  
  4. 29.   } else {  
  5. 30.     if (array[start] > *max) {  
  6. 31.       *max = array[start];  
  7. 32.     }  
  8. 33.     if (array[start] < *min) {  
  9. 34.       *min = array[start];  
  10. 35.     }  
  11. 36.   }  

37. }  


为了测试性能,完成比较程序如下:

[cpp] view plaincopy

  1. #include <stdio.h>  
  2. #include <vector>  
  3. #include <stdlib.h>  
  4. #include <sys/time.h>  
  5. template<typename T>  
  6. bool MaxMin(std::vector<T> array, T* max, T* min) {  
  7.   if (array.size() < 1) {  
  8.     return false;  
  9.   }  
  10. 10.   *max = array[0];  
  11. 11.   *min = array[0];  
  12. 12.   size_t array_size = array.size();  
  13. 13.   for (int i = 1; i < array_size; ++i) {  
  14. 14.     if (array[i] > *max) {  
  15. 15.       *max = array[i];  
  16. 16.     } else if (array[i] < *min) {  
  17. 17.       *min = array[i];  
  18. 18.     }  
  19. 19.   }  
  20. 20.   return true;  

21. }  

22. template<typename T>  

23. bool MaxMin_1(std::vector<T> array, T* max, T* min) {  

  1. 24.   if (array.size() < 1) {  
  2. 25.     return false;  
  3. 26.   }  
  4. 27.   *max = array[0];  
  5. 28.   *min = array[0];  
  6. 29.   int index = 1;  
  7. 30.   int array_size = array.size();  
  8. 31.   while(index < array_size && index +1 <array_size) {  
  9. 32.     if (array[index] >= array[index + 1]) {  
  10. 33.       if (array[index] > *max) {  
  11. 34.         *max = array[index];  
  12. 35.       }  
  13. 36.       if (array[index + 1] < *min) {  
  14. 37.         *min = array[index + 1];  
  15. 38.       }  
  16. 39.     } else {  
  17. 40.       if (array[index + 1] > *max) {  
  18. 41.         *max = array[index + 1];  
  19. 42.       }  
  20. 43.       if (array[index] < *min) {  
  21. 44.         *min = array[index];  
  22. 45.       }  
  23. 46.     }  
  24. 47.     index += 2;  
  25. 48.   }   
  26. 49.   if (index < array.size()) {  
  27. 50.     if (array[index] > *max) {  
  28. 51.       *max = array[index];  
  29. 52.     }  
  30. 53.     if (array[index] < *min) {  
  31. 54.       *min = array[index];  
  32. 55.     }  
  33. 56.   }  
  34. 57.   return true;  

58. }  

59. template<typename T>  

60. bool MaxMin_2(std::vector<T> array, int start, int end, T* max, T* min) {  

  1. 61.   if (end - start > 1) {  
  2. 62.     MaxMin_2(array, start, (start + end) / 2, max, min);  
  3. 63.     MaxMin_2(array, (start + end) / 2 + 1, end, max, min);  
  4. 64.   } else {  
  5. 65.     if (array[end] > array[start]) {  
  6. 66.       if (array[end] > *max) {  
  7. 67.         *max = array[end];  
  8. 68.       }  
  9. 69.       if (array[start] < *min) {  
  10. 70.           *min = array[start];  
  11. 71.       }  
  12. 72.     } else {  
  13. 73.       if (array[start] > *max) {  
  14. 74.         *max = array[start];  
  15. 75.       }  
  16. 76.       if (array[end] < *min) {  
  17. 77.         *min = array[end];  
  18. 78.       }  
  19. 79.     }  
  20. 80.   }  

81. }  

82. template<typename T>  

83. bool MaxMin_3(std::vector<T> array, int start, int end, T* max, T* min) {  

  1. 84.   if (end > start) {  
  2. 85.     MaxMin_2(array, start, (start + end) / 2, max, min);  
  3. 86.     MaxMin_2(array, (start + end) / 2 + 1, end, max, min);  
  4. 87.   } else {  
  5. 88.     if (array[start] > *max) {  
  6. 89.       *max = array[start];  
  7. 90.     }  
  8. 91.     if (array[start] < *min) {  
  9. 92.       *min = array[start];  
  10. 93.     }  
  11. 94.   }  

95. }  

  1. 96.   

97. int GetTime() {  

  1. 98.   timeval tv;  
  2. 99.   gettimeofday(&tv, NULL);  
  3. 100.   return tv.tv_sec * 1000000 + tv.tv_usec;  

101. }  

102. int main(int argc, char** argv) {  

  1. 103.   const int kArraySize = 10000;  
  2. 104.   std::vector<int> array;  
  3. 105.   for (int i = 0; i < kArraySize; ++i) {  
  4. 106.     array.push_back(rand());  
  5. 107.     //    printf("%d ", array[i]);  
  6. 108.   }  
  7. 109.   printf("\n");  
  8. 110.   int max;  
  9. 111.   int min;  
  10. 112.   int start;  
  11. 113.   start = GetTime();  
  12. 114.   MaxMin(array, &max, &min);  
  13. 115.   printf("time elapse:%d\n", GetTime() - start);  
  14. 116.   printf("max:%d min:%d\n", max, min);  
  15. 117.   
  16. 118.   start = GetTime();  
  17. 119.   MaxMin_1(array, &max, &min);  
  18. 120.   printf("time elapse:%d\n", GetTime() - start);  
  19. 121.   printf("max:%d min:%d\n", max, min);  
  20. 122.   start = GetTime();  
  21. 123.   MaxMin_2(array, 0, array.size() - 1, &max, &min);  
  22. 124.   printf("time elapse:%d\n", GetTime() - start);  
  23. 125.   printf("max:%d min:%d\n", max, min);   
  24. 126.   start = GetTime();  
  25. 127.   MaxMin_3(array, 0, array.size() - 1, &max, &min);  
  26. 128.   printf("time elapse:%d\n", GetTime() - start);  
  27. 129.   printf("max:%d min:%d\n", max, min);   

130. }  


执行结果:

[cpp] view plaincopy

  1. ./a.out   
  2.   
  3. time elapse:187  
  4. max:2147469841 min:100669  
  5. time elapse:216  
  6. max:2147469841 min:100669  
  7. time elapse:86513  
  8. max:2147469841 min:100669  
  9. time elapse:82481  

10. max:2147469841 min:100669  


结论:最简单的方法效率最高,分治法由于迭代效率非常差,这是我想到了分治法的归并排序,估计性能也不会好,改天比较一下。

寻找数组中的最大值和最小值
《编程之美》2.10
算法1:
if(arr[0] > arr[1])
max=arr[0]
min=arr[1]
else
max=arr[1]
min=arr[0]
loop:i从3到n
if(max < arr[i])
   max=arr[i]
else
   if(min > arr[i])
    min = arr[i]
平均比较次数:1+n-2+(n-2)/2=3*(n-2)/2+1
算法2:
if(arr[0] > arr[1])
max=arr[0]
min=arr[1]
else
max=arr[1]
min=arr[0]
loop:i从3到n(i每次递增2)
if(arr[i] > arr[i+1])
   if(arr[i] > max)
    max=arr[i]
   if(arr[i+1]<min)
    min=arr[i+1]
else
   if(arr[i] < min)
    min=arr[i]
   if(arr[i+1] > max)
    max = arr[i+1]
比较次数:1+3*(n-2)/2
代码:
#include <iostream>

using namespace std;

//algorithm
void maxMin1(int *arr, int b, int e){
int max, min;
if (arr[b] < arr[b+1])
{
   max = arr[b+1];
   min = arr[b];
}else{
   max = arr[b];
   min = arr[b+1];
}

for (int i = b + 2; i < e; i += 2)
{
   if (arr[i] < arr[i +1])
   {
    if (max < arr[i+1])
     max = arr[i+1];
    if (min > arr[i])
     min = arr[i];
   }else{
    if (max < arr[i])
     max = arr[i];
    if (min > arr[i+1])
     min = arr[i+1];
   }
}

if ((e - b)%2)
{
   if (arr[e-1] > max)
    max = arr[e-1];
   if (arr[e-1] < min)
    min = arr[e-1];
}

cout << "max = " << max << ", min = " << min << endl;
}


//algorithm:divide and conquer
void maxMinDivideAndConquer(int *arr, int b, int e, int &max, int &min){
if (e - b == 1)
{
   max = arr[b];
   min = arr[b];
   return;
}

if (e - b == 2)
{
   if (arr[b] < arr[b+1])
   {
    max = arr[b+1];
    min = arr[b];
   }else{
    max = arr[b];
    min = arr[b+1];
   }
   return;
}

int mid = b + (e-b)/2;
int leftMax, leftMin;
maxMinDivideAndConquer(arr, b, mid, leftMax, leftMin);
int rightMax, rightMin;
maxMinDivideAndConquer(arr, mid, e, rightMax, rightMin);

if (leftMax > rightMax)
   max = leftMax;
else
   max = rightMax;

if (leftMin < rightMin)
   min = leftMin;
else
   min = rightMin;
}

void main(){
int arr1[] = {6, 5, 8, 3, 9, 7};
int arr2[] = {6, 5, 8, 3, 9, 7, 20};
// maxMin1(arr1, 0, 6);
// maxMin1(arr2, 0, 7);
int max, min;
maxMinDivideAndConquer(arr1, 0, 6, max, min);
cout << "max = " << max << ", min = " << min << endl;
maxMinDivideAndConquer(arr2, 0, 7, max, min);
cout << "max = " << max << ", min = " << min << endl;
}

扩展问题:要找出N个数组中的第二大数。
法1:通过n-1次比较,找出最大数;在除去最大数的数组中找最大数。比较次数:n-1+n-2=2n-3
法2:把数组中的元素每两个分为一组,每组中的最大数为F,第二大数为S。假设现在已知相邻两组的最大数和第二大数分别是:Fi,Si,Fj,Sj,。则这两组合并为一组后,其中最大数和第二大数可能是:
1、若Fi > Fj,则最大数是Fi;
若Si>Fj,则第二大数是Si;否则,第二大数是Fj
2、若Fi < Fj,则最大数是Fj
若Fi>Sj,则第二大数是Fi;否则,第二大数是Sj
共有N/2组,每组需要比较一次得出本组的最大数和第二大数;共需比较N/2 * 2次。
法3.、分治法divide and conquer
把数组分成两部分,其最大数和第二大数分别是:Fleft,Sleft,Fright,Sright。合并时的情况可能为:
1、Fleft > Fright,最大数是Fleft;若Sleft>Fright,则第二大数是Sleft,否则第二大数是Fright;
2、 Fleft < Fright,最大数是Fright;若Fleft>Sright,则第二大数Fleft,否则第二大数是Sright。
算法如下:
secondMax(int begin, int end, int F, int S)
if(begin + 1 == end)
   if(a[begin] > a[end])
    F = a[begin]
    S = a[end]
   else
    F = a[end]
    S = a[begin]
int mid = begin + (end - begin)/2;
secondMax(begin, mid, Fleft, Sleft)
secondMax(mid+1, right, Fright, Sright)
if(Fleft > Fright)
   F = Fleft
   if(Sleft > Fright)
    S = Sleft
   else
    S = Fright
else
   F = Fright
   if(Fleft > Sright)
    S = Fleft
   else
    S = Sright
比较次数:设n=2^(k+1)
F(n)=2*F(n/2)+2
=2*( 2*F(n/2^2) + 2) + 2
=2^2 * F(n/2^2) + 2^2 + 2
=2^2 * (2*F(n/2^3) + 2) + 2^2 +2
=2^3*F(n/2^3) + 2^3 + 2^2 + 2
=2^k * F(n/2^k) + 2^k + 2^(k-1) + …+ 2^2 + 2^1
=2^k*F(2)+2^k+2^(k-1)+…+2^2+2^1
=2^(k+1)+2^k+…+2^1
=2*n-2

寻找数组中最大值和最小值

解法一:

扫描一次数组找出最大值;

再扫描一次数组找出最小值。

代码(略) 

比较次数2N-2

 

解法二:

将数组中相邻的两个数分在一组, 每次比较两个相邻的数,将较大值交换至这两个数的左边,较小值放于右边。

对大者组扫描一次找出最大值,对小者组扫描一次找出最小值。

代码(略)

比较1.5N-2次,但需要改变数组结构

 

解法三:

每次比较相邻两个数,较大者与MAX比较,较小者与MIN比较,找出最大值和最小值。

代码如下:

 

void GetMaxAndMin(int* arr, int len, Result* rlt)
{
    for(int i=2; i< len-1; i=i+2)
    {
        if(NULL==arr[i+1])
        {
            if(arr[i]>rlt->Max)
                rlt->Max=arr[i];
            if(arr[i]<rlt->Min)
                rlt->Min=arr[i];
        }
        if(arr[i]>arr[i+1])
        {
            if(arr[i]>rlt->Max)
                rlt->Max=arr[i];
            if(arr[i+1]<rlt->Min)
                rlt->Min=arr[i+1];
        }
        if(arr[i]<arr[i+1])
        {
            if(arr[i+1]>rlt->Max)
                rlt->Max=arr[i+1];
            if(arr[i]<rlt->Min)
                rlt->Min=arr[i];
        }
    }
}

 

比较次数1.5N-2,但是不用改变原数组结构。

 

解法四:

分治法,算出前N/2个数的MAX和MIN,再算出后N/2个数的MAX和MIN。代码如下:

 

void GetMaxAndMin1(int* arr, int len, Result* rlt)
{
    if(len==0||!arr)
        return;
    if(len==1)
    {
        if(arr[0]>rlt->Max)
            rlt->Max=arr[0];
        if(arr[0]<rlt->Min)
            rlt->Min=arr[0];
        return;
    }
    GetMaxAndMin(arr, len/2, rlt);
    GetMaxAndMin(&arr[len/2], len-len/2, rlt);
}

 

需比较1.5/N-2次。

 

试验代码:

 

#include "stdio.h"
#include "stdlib.h"

#define LEN(arr) sizeof(arr)/sizeof((arr)[0])

struct Result{
    int Max;
    int Min;
};

int main()
{
    int test[10]={3,2,4,1,5,2,7,9,0};
    Result* rlt = (Result*)malloc(sizeof(Result));
    rlt->Max = rlt->Min = test[0];
    int len=LEN(test);
    GetMaxAndMin(test, len, rlt);
    printf("Max=%d\nMin=%d\n", rlt->Max, rlt->Min);
    getchar();
}