Leetcode题集——maximum-subarray

来源:互联网 发布:林心如律师发声明知乎 编辑:程序博客网 时间:2024/05/29 02:51

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array[−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray[4,−1,2,1]has the largest sum =6.

click to show more practice.

解析:求一个输入数组的连续子序列的最大和值。

方法一:动态规划法:

时间复杂度为O(n)。

设sum[i]为以第i个元素结尾且和最大的连续子数组。假设对于元素i,所有以它前面的元素结尾的子数组的长度都已经求得,那么以第i个元素结尾且和最大的连续子数组实际上,要么是以第i-1个元素结尾且和最大的连续子数组加上这个元素,要么是只包含第i个元素,即sum[i] = max(sum[i-1] + a[i], a[i])。可以通过判断sum[i-1] + a[i]是否大于a[i]来做选择,而这实际上等价于判断sum[i-1]是否大于0。由于每次运算只需要前一次的结果,因此并不需要像普通的动态规划那样保留之前所有的计算结果,只需要保留上一次的即可,因此算法的时间和空间复杂度都很小。

class Solution {public:    bool invalidinput=false;    int maxSubArray(int A[], int n)     {       if(A==NULL||n<=0)       {          invalidinput=true;           return 0;       }        invalidinput=false;                int cursum=0;        int sum=0x80000000;        for(int i=0;i<n;i++)        {           if(cursum<=0)               cursum=A[i];           else               cursum+=A[i];                        if(cursum>sum)                sum=cursum;        }        return sum;    }};
方法二、分治方法

也就是递归求解。时间复杂度为O(nlogn)。这是个分治的思想,解决复杂问题我们经常使用的一种思维方法——分而治之。

而对于此题,我们把数组A[1..n]分成两个相等大小的块:A[1..n/2]和A[n/2+1..n],最大的子数组只可能出现在三种情况:
    A[1..n]的最大子数组和A[1..n/2]最大子数组相同;
    A[1..n]的最大子数组和A[n/2+1..n]最大子数组相同;
    A[1..n]的最大子数组跨过A[1..n/2]和A[n/2+1..n]
前两种情况的求法和整体的求法是一样的,因此递归求得。
第三种,我们可以采取的方法也比较简单,沿着第n/2向左搜索,直到左边界,找到最大的和maxleft,以及沿着第n/2+1向右搜索找到最大和maxright,那么总的最大和就是maxleft+maxright。因为要跨过中间点,因此返回必须为maxleft和maxright之和!
而数组A的最大子数组和就是这三种情况中最大的一个。

int find_max_crossing(int arr[],int low,int mid,int high,int *left,int *right){  int lsum=-100;  int sum=0;    for(int i=mid;i>=low;--i)  {    sum+=arr[i];if(sum>lsum){  lsum=sum;   *left=i;}  }    int rsum=-100;    sum=0;  for(int j=mid+1;j<=high;j++)  {     sum+=arr[j];if(sum>rsum){  rsum=sum;  *right=j;}  }  return rsum+lsum;}int max_sum_array(int arr[],int low,int high,int *left,int *right){   if(low==high)   {//递归结束点     *left=low; *right=high; return arr[low];   }      int mid=(low+high)/2;   int lleft,lright,rleft,rright,mleft,mright;      //三种情况下分别求解   int lmax=max_sum_array(arr,low,mid,&lleft,&lright);   int rmax=max_sum_array(arr,mid+1,high,&rleft,&rright);   int mmax=find_max_crossing(arr,low,mid,high,&mleft,&mright);   //返回最大值   if(lmax>rmax&&lmax>mmax)   {     *left=lleft; *right=lright; return lmax;   }   if(rmax>lmax&&rmax>mmax)   {     *left=rleft; *right=rright; return rmax;   }   if(mmax>lmax&&mmax>rmax)   {     *left=mleft; *right=mright; return mmax;   }  }


0 0
原创粉丝点击