LeetCode: Maximum Subarray

来源:互联网 发布:js filter 实现 编辑:程序博客网 时间:2024/06/06 01:45

问题:
这里写图片描述
这是一个最大子序列和的问题,首先需要明确子序列是连续的。一个长度为n的序列中有n(n+1)/2个子序列,所以如果用穷举法(暴力搜索)的话,时间复杂度至少为o(n^2),所以需要探寻更高效的算法。

解法一:
分治法:将序列一分为二,那么能得到最大值的子序列可能在左边的序列中,可能在右边的序列中,也可能一半在左边的序列,一半在右边的序列中,比较这三个值的大小,输出最大的值。持续将序列一分为二,类似于二分搜索,最后能得到最大的子序列之和。算法的复杂度为o(nlogn)。实现代码如下:

class Solution {public:    //递归实现分治算法,返回最大的序列和    int dnc(vector<int>& nums,int left,int right)    {        if(left==right) return nums[left];//终止条件        int mid=(left+right)/2;        int maxLeftSum=dnc(nums,left,mid-1);//分治后左边的最大值        int maxRightSum=dnc(nums,mid+1,right);//分治后右边的最大值        //求分治后一半左边一半右边的最大值        int maxMidSum=nums[mid];        int temp=nums[mid];        for (int i=mid-1;i>=left;i--)        {            temp+=nums[i];            if(temp>maxMidSum) maxMidSum=temp;        }        temp=maxMidSum;        for (int i=mid+1;i<=right;i++)        {            temp+=nums[i];            if(temp>maxMidSum) maxMidSum=temp;        }        //返回三个最大值中的最大值        int maxSum=maxLeftSum;        if(maxMidSum>maxSum) maxSum=maxMidSum;        if(maxRightSum>maxSum) maxSum=maxRightSum;        return maxSum;    }    int maxSubArray(vector<int>& nums) {        int len=nums.size();        return dnc(nums,0,len-1);    }};

解法二:
网上还有一个算法复杂度为o(n)的更高效算法:已知了前k个元素的最大子序列和为maxSum,寻找第k+1这个元素。由于连续子序列的限制,如果第k+1个元素之前的和是小于0的,那么对于增大k+1这个元素从而去组成最大子序列是没有贡献的,所以可以把第K+1个元素之前的和置0。
例如,在序列-1,-2,7中,对7来说,之前的和sum=-1+(-2)<0,会拖累7成为待选的最大子序列,所以将sum置为0;而在序列-1,-2,7,5中,5之前的sum=7不会拖累5成为待选的最大子序列,所以sum=5。
Accepted的代码:

class Solution {public:    int maxSubArray(vector<int>& nums) {        int len=nums.size();        int sum=nums[0],maxSum=nums[0];          for(int i = 1; i<len; i++)        {              if(sum<0) sum=0;   //判断K+1个元素之前的和是否会拖累它              sum+=nums[i];              if(sum>maxSum) maxSum=sum;           }          return maxSum;      }};
0 0
原创粉丝点击