最大子数组问题

来源:互联网 发布:网络玻璃的意思是什么 编辑:程序博客网 时间:2024/06/06 01:21

在leetcode上看到的求最大子数组问题,在算法导论上分治策略章节中也有相同的问题,在这里介绍两种算法。
第一种,用分治法的思想去求解,先将数组对半分,那么,最大子数组的位置有三种情况,1.子数组全部在中点的右边,2.子数组全部在中点的左边。3.子数组部分在中点的左边,另一部分在中点的右边。
只要分别求出这三种情况的最大值比较,取最大的即为最大子数组。
第三种情况最简单只要从中点出发,向左递减,向右递增。分别找出左右和的最大值即可。下面是代码

int maxArr(int *arr,int start,int length){    int sum1 = 0,sum2 = 0,max1 = arr[(length +start)/ 2],max2 = arr[(length + start) / 2];    /*        求出中点左边到中点的和的最大值    */    for(int i = (length + start)/ 2;i >= start;i--)    {        sum1 += arr[i];        if(sum1 > max1)            max1 = sum1;    }    /*        求出中点右边到中点的和的最大值    */    for(int i = (length + start)/ 2;i < length;i++)    {        sum2 += arr[i];        if(sum2 > max2)            max2 = sum2;    }    return max1 + max2 - arr[(length + start) / 2];}

那么在中点右边和左边怎么求呢。其实就是求中点左边的数组的最大子数组。这样依然是上述的三种情况。那么就把原数组分成了一个较小的数组。只须递归求解。中点右边也是相同的思想。
这个算法的思想是记录目前为止已经处理过的最大子数组。若已知a[1…j]的最大子数组,那么a[1…j+1]的最大子数组要么是a[1…j]的最大子数组,要么是摸个子数组a[i…j+1]。

int subMax(int *arr,int start,int length){    int max1 = maxArr(arr,start,length);//求出第三种情况的最大值    /*    求出第一种情况的最大值    */       if(((length + start) / 2 - 1) >= start)        {            int max2 = subMax(arr,start,(length + start) / 2);            if(max2 > max1)                max1 = max2;        }        /*        求出第二种情况的最大值        */    if(((length + start) / 2 + 1) < length)        {            int max3 = subMax(arr,(length + start) / 2 + 1,length);            if(max3 > max1)                max1 = max3;        }    return max1;}

用这种方法的求解时间复杂度为o(nlgn),下面介绍一种时间复杂度为o(n)的算法。
下面用c++实现。

int maxSubArray(vector<int>& nums) {        int max = nums[0],j = 1,sum = nums[0];        while(j < nums.size())        {            if(nums[j] > max)            max = nums[j];            if((sum + nums[j]) < (nums[j] + nums[j - 1]))                sum = nums[j] + nums[j - 1];            else                sum += nums[j];             if(sum > max)            max = sum;            j++;        }
原创粉丝点击