关于如何查找数组中和最大的子数组

来源:互联网 发布:汉诺塔递归算法复杂度 编辑:程序博客网 时间:2024/05/22 17:09

题目:

输入一个整型数组,数据元素有正数也有负数,求元素组合成连续子数组之和最大的子数组,要求时间复杂度为O(n)

例如:

输入的数组为1, -2, 3, 10, -4, 7, 2, -5,最大和的连续子数组为3, 10, -4, 7, 2,其最大和为18

背景:

本题最初为2005年浙江大学计算机系考研题的最后一道程序设计题,在2006年里包括google在内的很多知名公司都把本题当作面试题。

由于本题在网络中广为流传,本题也顺利成为2006年程序员面试题中经典中的经典。

int MaxSub(int a[],int n,int& begin,int& end)//a[]是给定的数组,n是数组中元素个数,begin和end分别记录起始项和末项{  int sum=0;//最大子段和 int b=0;//最后一项为a[i]的序列构成的最大子段和 for(int i=0;i<n;i++) {  if(b>0)  {   b=b+a[i];  }  else  {   b=a[i];   begin=i;//记录起始项  }  if(b>sum)  {   sum=b;   end=i;//记录末项  } }   if(end==0)  {  表示所有数都为负数;这时要找出数组中最大的数; } return sum;}程序结果:输入数组{-1,3,6,-9,2,-5,-1,9,3,-3}得到最大和子序列{9,3}



        /// <summary>        /// 获取连续子数组的最大和        /// </summary>        /// <param name="array">目标数组</param>        /// <param name="length">数组的长度</param>        private static void GetMaxSum(int[] array, int length)        {            int sum = 0;    //记录当前连续子数组的最大和            int temp = 0;   //记录当前数组连续几个元素的和(当其值小于0时,重新对其赋值;【即:抛弃前面的所有元素】)            int startIndex = 0; //记录子数组(和最大)的起始位置            int endIndex = 0;   //记录子数组(和最大)的终止位置            int newStartIndex = 0;  //记录子数组(和最大)的新的起始位置            for (int i = 0; i < length; i++)    //遍历整个目标数组            {                if (temp < 0)   //如果temp < 0;则要对temp重新赋值                {                    temp = array[i];    //对temp重新赋值                    newStartIndex = i;  //暂时记录子数组(和最大)的新的起始位置(要看后续的sum 和 temp是否发生交换)                }                else                {                    temp += array[i];   //如果temp >= 0;则要继续将此时的数组元素(array[i])加入到temp中                }                if (sum < temp) //如果此时 sum < temp;则表示此时的子数组和大于之前的子数组和                {                    sum = temp; //将大的子数组和temp赋值给sum                    startIndex = newStartIndex; //子数组(和最大)的新的起始位置起作用了                    endIndex = i;   //子数组(和最大)的终止位置(只要发生交换就说明endIndex发生变化)                }            }            //显示最终的结果(从数组的第N个元素到M个元素之和最大)            DisplayResult(array, sum, startIndex, endIndex);        }

讨论:上述代码中有两点值得和大家讨论一下:

·         函数的返回值不是子数组和的最大值,而是一个判断输入是否有效的标志。如果函数返回值的是子数组和的最大值,那么当输入一个空指针是应该返回什么呢?返回0?那这个函数的用户怎么区分输入无效和子数组和的最大值刚好是0这两中情况呢?基于这个考虑,本人认为把子数组和的最大值以引用的方式放到参数列表中,同时让函数返回一个函数是否正常执行的标志。

·         输入有一类特殊情况需要特殊处理。当输入数组中所有整数都是负数时,子数组和的最大值就是数组中的最大元素。

本文已经收录到《剑指Offer——名企面试官精讲典型编程题》一书中,有改动,书中的分析讲解更加详细,讨论了这种方法和动态规划方法的联系。欢迎关注。在我的英文博客里也有这道题的讲解,


0 0