关于求最大连续子数组和的问题
题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。本来是想看看算法导论的,遇到这个问题,书上写的完全不知道说的什么?看博客发现有很多方法,可惜我不太想看,自己想了下觉得这个问题应该不难。
程序代码:
using System; namespace arraytest { class program { public static void Main(string[] args) { int[] array=new int[]{1,-2,5,-3,9,-4,7,2,-8,10};//求这个数组里面的最大连续子数组 int sum=0,maxleft=0,maxright=0;//定义从数组左边开始求和的最大值为maxleft,右边为maxright int maxindexright=0,maxindexleft=0;//定义maxleft的索引为maxindexright,右边也一样 for(int i=0;i<array.Length;i++) { sum+=array[i]; if(sum>maxleft) { maxleft=sum; maxindexright=i; } } sum=0; //找到最大的右下标后,以之为起点,求左下标 for(int i=maxindexright;i!=0;i--) { sum+=array[i]; if(sum>maxright) { maxright=sum; maxindexleft=i; } } Console.WriteLine("最大连续子数组的下标分别是:{0},{1}",maxindexleft,maxindexright); Console.WriteLine("最大连续子数组的和为:{0}",maxright); Console.ReadKey(); } } }输出:
最大连续子数组的下标分别是:2,9
最大连续子数组的和为:18
证明:
其实我想说的是,你如果从左右起点开始求和的话,那么你找到的那个最大和的下标和最大连续子数组的下标是相同的。
反证法:假设不同,最大连续子数组的右下标比最大和的右下标大,多出来的那部分它的和一定为负数,因为如果为正数,
那么最大和的下标一定不是目前这个下标。但如果多出来的那部分和为负数,那么一定不是最大连续子数组,
因为最大连续子数组没必要多加上一个负数。
所以最大和右下标和最大连续子数组右下标只能相同。
反之,左下标也只能一样。我们从右端开始计数就明白了。
当然我上面,做了个简化,没有从最右端计数,而是从找到的最大右坐标开始计数,这个道理容易想通,我不多说。
算法复杂度不是很懂,但是这个算法主要是遍历了两次数组求和。复杂度应该和n的个数成正比。不知道求和会影响性能。
大家觉得怎么样?
还有大家平时是怎么学算法的,自学如何比较快的入门?