LeetCode第53题
题目描述:
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-subarray
思路
采用分治法来做,时间复杂度会比较低。将数组分为左子数组和右子数组。那么最大子序就有三种存在位置:完全被包含于左子数组,完全被包含于右子数组,跨越中点同时存在于左右两个子数组中。对于前两种情况,可以递归求解。
对于最后一种情况,需要独立考虑。因为必然跨越中点,所以子序中必然包含中点。所以从中点开始,分别向左向右搜寻最大的序列和。最后将左右最大序列号相加。
源代码
int maxSubArray(int* nums, int numsSize){
return find_max_subarray(nums,0,numsSize - 1);
}
int find_max_subarray(int A[],int low,int high){
int mid,left_sum,right_sum,cross_sum;
if(low == high)
return A[low];
else{
int mid = (low + high) / 2;
left_sum = find_max_subarray(A,low,mid);
right_sum = find_max_subarray(A,mid + 1,high);
cross_sum = find_max_cross_subarray(A,low,mid,high);
}
if(left_sum >= right_sum && left_sum >= cross_sum)
return left_sum;
else if(right_sum >= left_sum && right_sum >= cross_sum)
return right_sum;
else
return cross_sum;
}
int find_max_cross_subarray(int A[],int low,int mid,int high){
int left_sum = A[mid];
int sum = 0;
for(int i = mid;i >= low;--i){
sum = sum + A[i];
if(sum > left_sum){
left_sum = sum;
}
}
int right_sum = A[mid + 1];
sum = 0;
for(int j = mid + 1;j <= high;++j){
sum = sum + A[j];
if(sum > right_sum){
right_sum = sum;
}
}
return (left_sum + right_sum);
}
分析
时间复杂度为O(nlgn),空间复杂度为常数级别(不包含递归时所开辟函数的栈空间)。
网友评论