zoukankan      html  css  js  c++  java
  • 最大子数组求解法

    给出一个数组

    int[] priceArray = { 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97 };
    

    求其中的最大子数组

    暴力求解

    思路:通过两层for循环遍历该数组中的每一个子数组,然后统计每一个子数组的和,每求出一次子数组的和便进行一次判断,来保存下最大子数组和对应的下标。

            static void Main(string[] args)
            {
                int[] priceArray = { 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97 };
                int[] priceFluctuationArray = new int[priceArray.Length - 1];
    
                for(int i = 1; i < priceArray.Length; i++)
                {
                    priceFluctuationArray[i - 1] = priceArray[i] - priceArray[i - 1];
                }
    
                int total = priceFluctuationArray[0], startIndex = 0, endIndex = 0;
    
                for(int i = 0; i < priceFluctuationArray.Length; i++)
                {
                    for(int j = i; j < priceFluctuationArray.Length; j++)
                    {
                        int temp = 0;
                        for(int index = i; index <= j; index++)
                        {
                            temp += priceFluctuationArray[index];
                        }
    
                        if (temp > total)
                        {
                            total = temp;
                            startIndex = i;
                            endIndex = j + 1;
                        }
                    }
                }
                Console.WriteLine($"start:{startIndex},end:{endIndex},total:{total}");
            }
        }
    

    上列代码中采用了三层for循环,前面两层是遍历全部子数组,最后一层则是将该子数组求和,性能耗费很大,但是也算是一种求解方法,建议走投无路的时候再采用。

    分治法

    分治法则是采用二分法和递归来实现。

    首先取得中间值mid。

    所有的情况分为以下三大类

    1. 位于低区间
    2. 位于高区间
    3. 跨区间

    1与2的情况都可以归为求区间内的最大子数组问题,这么一想是不是就和最开始要求的问题一样了?只不过是将一个大区间划分为小区间进行操作,所以1和2的情况便是可以通过递归操作来进行完成。

    每一个递归都需要设定终止条件,在无法继续划分更小的区间的时候,便是结束递归的时候,也就是 low == high的时候便结束递归。

    最后是情况3,我们需要对低区间求出最大的子数组,对高区间求出最大子数组,两者子数组之和便是我们所需要的结果。

    讨论完以上三种情况,我们需要的是对所有的情况进行一个结果的对比,取出最大的值。

            struct MaxSubArr
            {
                public int startIndex;
                public int endIndex;
                public int total;
            }
    
            static void Main(string[] args)
            {
                int[] priceArray = { 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97 };
                int[] priceFluctuationArray = new int[priceArray.Length - 1];
    
                for (int i = 1; i < priceArray.Length; i++)
                {
                    priceFluctuationArray[i - 1] = priceArray[i] - priceArray[i - 1];
                }
    
                MaxSubArr arr = GetMaxSubArr(0, priceFluctuationArray.Length - 1, priceFluctuationArray);
    
                Console.WriteLine($"开始{arr.startIndex},结束{arr.endIndex + 1},总和{arr.total}");
    
            }
    
            static MaxSubArr GetMaxSubArr(int low,int high,int[] arr)
            {
                if(low == high)
                {
                    MaxSubArr Arr;
                    Arr.startIndex = low;
                    Arr.endIndex = high;
                    Arr.total = arr[low];
                    return Arr;
                }
    
                int mid = (low + high) / 2;
    
                //低区间
                MaxSubArr Arr1 = GetMaxSubArr(low, mid, arr);
    
                //高区间
                MaxSubArr Arr2 = GetMaxSubArr(mid + 1, high, arr);
    
                //低高区间
                int startIndex = mid, endIndex = mid + 1, total1 = 0, total2 = 0, tempTotal = 0;
    
                for(int i = mid; i >= low; i--)
                {
                    tempTotal += arr[i];
                    if(tempTotal > total1)
                    {
                        total1 = tempTotal;
                        startIndex = i;
                    }
                }
    
                tempTotal = 0;
                for(int i = mid+1;i <= high; i++)
                {
                    tempTotal += arr[i];
                    if (tempTotal > total2)
                    {
                        total2 = tempTotal;
                        endIndex = i;
                    }
                }
    
                MaxSubArr Arr3;
                Arr3.startIndex = startIndex;
                Arr3.endIndex = endIndex;
                Arr3.total = total1 + total2;
    
                if (Arr1.total > Arr2.total && Arr1.total > Arr3.total)
                {
                    return Arr1;
                }else if(Arr2.total > Arr1.total && Arr2.total > Arr3.total)
                {
                    return Arr2;
                }
                else
                {
                    return Arr3;
                }
            }
    
  • 相关阅读:
    多线程博文地址 http://www.cnblogs.com/nokiaguy/archive/2008/07/13/1241817.html
    vs2010一运行就报错deven.exe assert failure 解决方法,卸载系统中.netFramework最新版本的(简体中文)
    Lambda语句中创建自定义类型时,也可指定某种特定类型,方法是在new与{}之间写上类型名称
    Win7开始菜单所在目录
    C#中Struct与Class的区别
    Linq语句:三表联查
    用exp、dmp导入导出用户到同一个实例下时,类型type会有问题
    列、约束重命名,原数据不丢失
    CDM中,创建一个或多个组合属性的唯一约束
    EF中新建表和关联表的方法
  • 原文地址:https://www.cnblogs.com/lehanbal/p/12914975.html
Copyright © 2011-2022 走看看