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


    最简单的方法就是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(" ");  
    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 ", GetTime() - start);  
    14. 116.   printf("max:%d min:%d ", max, min);  
    15. 117.   
    16. 118.   start = GetTime();  
    17. 119.   MaxMin_1(array, &max, &min);  
    18. 120.   printf("time elapse:%d ", GetTime() - start);  
    19. 121.   printf("max:%d min:%d ", max, min);  
    20. 122.   start = GetTime();  
    21. 123.   MaxMin_2(array, 0, array.size() - 1, &max, &min);  
    22. 124.   printf("time elapse:%d ", GetTime() - start);  
    23. 125.   printf("max:%d min:%d ", max, min);   
    24. 126.   start = GetTime();  
    25. 127.   MaxMin_3(array, 0, array.size() - 1, &max, &min);  
    26. 128.   printf("time elapse:%d ", GetTime() - start);  
    27. 129.   printf("max:%d min:%d ", 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 Min=%d ", rlt->Max, rlt->Min);
        getchar();
    }

  • 相关阅读:
    【C#食谱】【风味小吃】菜单2:角度转换为弧度
    16 Rules for Managers
    word打不开,要在安全模式下才能打开
    禁止修改IP地址工具及原理
    VB编程读取本地计算机IP地址及MAC地址
    联想TinkCenter 8000T 安装XP需要修改CMOS
    使用nLite封装2003集成Raid卡驱动
    怎么样让台式机通过笔记本无线上网 台式机共享上网 笔记本当无线路由器 两台电脑一根网线
    VB使用ADODB操作数据库的常用方法
    转:[震惊] 这两天发现被穿的真正原因——QQ电脑管家
  • 原文地址:https://www.cnblogs.com/fickleness/p/3155011.html
Copyright © 2020-2023  润新知