zoukankan      html  css  js  c++  java
  • 编程之美2.10:寻找数组中的最大值和最小值

    编程之美2.10: 对于一个有N个整数组成的数组,需要比较多少次才能把最大值和最小值找出来呢?

    算法的思想是: 分而治之

    测试数据:----------------------------------------------------

    int [] input1 = { 94, 40, 49, 65, 21, 21, 106, 80, 92, 81, 679, 4, 61, 6, 237, 12, 72, 74, 29, 95, 265, 35, 47, 1, 61, 397, 52, 72, 37, 51, 1, 81, 45, 435, 7, 36, 57, 86, 81, 72 };

    最大数据:679

    最小数据:1

    第二大数:435

    --------------------------------------------------------------

    方法一:递归

      // 方法一: 递归法 (分而治之)
            public static void FindMaxAndMinValues(int[] array, int startIndex, int endIndex, out int max, out int min)
            {          
                int tempMaxL, tempMaxR, tempMinL, tempMinR;
                tempMaxL = tempMaxR = tempMinL = tempMinR = 0;
    
                if (endIndex - startIndex > 1)
                {
                    FindMaxAndMinValues(array, startIndex, startIndex + (endIndex - startIndex) / 2, out tempMaxL, out tempMinL);
                    FindMaxAndMinValues(array, startIndex + (endIndex - startIndex) / 2 + 1, endIndex, out tempMaxR, out tempMinR);
                }
                else
                {
                    if (array[startIndex] > array[endIndex])
                    {
                        max = array[startIndex];
                        min = array[endIndex];
                    }
                    else
                    {
                        max = array[endIndex];
                        min = array[startIndex];
                    }
    
                    return;
                }
    
                max = tempMaxL > tempMaxR ? tempMaxL : tempMaxR;
                min = tempMinL < tempMinR ? tempMinL : tempMinR;
            }

    方法二:非递归方式 

      // 方法二:  非递归的实现分而治之。
            public static void FindMaxAndMinValues2(int[] array, out int max, out int min)
            {
                int startIndex = 0;
    
                if (array.Length % 2 == 0) // 偶数
                {
                    max = array[0] > array[1] ? array[0] : array[1];
                    min = array[0] < array[1] ? array[0] : array[1];
                    startIndex = 2;
                }
                else // 奇数
                {
                    max = min = array[0];
                    startIndex = 1;
                }
    
                for (int i = startIndex; i < array.Length; i += 2)
                {
                    int tempMaxValue = Math.Max(array[i], array[i + 1]);
                    int tempMinValue = Math.Min(array[i], array[i + 1]);
    
                    if (tempMaxValue > max)
                    {
                        max = tempMaxValue;
                    }
    
                    if (tempMinValue < min)
                    {
                        min = tempMinValue;
                    }
                }
            }

    可以将递归的分而治之算法划分成以下的步骤:

    1) 从图1 4 - 2中的二叉树由根至叶的过程中把一个大问题划分成许多个小问题,小问题的大小为1或2。

    2) 比较每个大小为2的问题中的金块,确定哪一个较重和哪一个较轻。在节点DEFG上完成这种比较。大小为1的问题中只有一个金块,它既是最轻的金块也是最重的金块。

    3) 对较轻的金块进行比较以确定哪一个金块最轻,对较重的金块进行比较以确定哪一个金块最重。对于节点AC执行这种比较。根据上述步骤,可以得出程序1 4 - 1的非递归代码。该程序用于寻找到数组w [ 0 : n - 1 ]中的最小数和最大数,若n < 1,则程序返回f a l s e,否则返回t r u e。当n≥1时,程序1 4 - 1给M i n和M a x置初值以使w [ M i n ]是最小的重量,w [ M a x ]为最大的重量。首先处理n≤1的情况。若n>1且为奇数,第一个重量w [ 0 ]将成为最小值和最大值的候选值,因此将有偶数个重量值w [ 1 : n - 1 ]参与f o r循环。当n 是偶数时,首先将两个重量值放在for 循环外进行比较,较小和较大的重量值分别置为Min和Max,因此也有偶数个重量值w[2:n-1]参与for循环。在for 循环中,外层if 通过比较确定( w [ i ] , w [ i + 1 ] )中的较大和较小者。此工作与前面提到的分而治之算法步骤中的2) 相对应,而内层的i f负责找出较小重量值和较大重量值中的最小值和最大值,这个工作对应于3 )。

    for 循环将每一对重量值中较小值和较大值分别与当前的最小值w [ M i n ]和最大值w [ M a x ]进行比较,根据比较结果来修改M i n和M a x(如果必要)。

    下面进行复杂性分析。注意到当n为偶数时,在for 循环外部将执行一次比较而在f o r循环内部执行3 ( n / 2 - 1 )次比较,比较的总次数为3 n / 2 - 2。当n 为奇数时,f o r循环外部没有执行比较,而内部执行了3(n-1)/2次比较。因此无论n 为奇数或偶数,当n>0时,比较的总次数为「3n/2ù-2次

    引申

    1. 如果需要找出N个数组中的第二大数,需要比较多少次呢?是否可以使用类似的分而治之思想来降低比较的次数呢?

     

    // 寻找第二大的数.(分而治之)
            public static void FindSecondMaxValue(int[] array, out int max, out int secondMax)
            {
                max = secondMax = 0;
    
                int startIndex = 0;
    
                if (array.Length % 2 == 0) // 偶数
                {
                    max = array[0] > array[1] ? array[0] : array[1];
                    secondMax = array[0] < array[1] ? array[0] : array[1];
                    startIndex = 2;
                }
                else // 奇数
                {
                    max = secondMax = array[0];
                    startIndex = 1;
                }
    
                for (int i = startIndex; i < array.Length; i += 2)
                {
                    int tempMaxValue = Math.Max(array[i], array[i + 1]);               
    
                    if (tempMaxValue > max)
                    {
                        secondMax = max;
                        max = tempMaxValue;
                    }
                    else
                    {
                        if (tempMaxValue > secondMax)
                        {
                            secondMax = tempMaxValue;
                        }
                    }
                }
            }
  • 相关阅读:
    轮播图
    MySQL初认识
    css的动画
    jQuery 滚动监听总结
    DOM操作 练习
    Ajax总结
    日历 练习
    Jquery基础
    2018-07-14Java基础+基本数据类型+自动/强制数据类型转换+定义变量+运算符
    2018-07-13E-R图设计数据库+三大范式+修改用户密码+分配用户权限
  • 原文地址:https://www.cnblogs.com/Jessy/p/3507351.html
Copyright © 2011-2022 走看看