Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
给定一个整数数组nums,找到具有最大总和的连续子数组(至少包含一个数),并返回该最大总和。
例子:
Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
看一下下面的内容:
如果你已经找到一个O(n)的解法,尝试使用分治法去编写另一种解法,这种解法更加微妙。
这题有三种解法,以下依次分析这三种解法。
该方法就是一次遍历,思路很简单,如下:
首先声明一个整数变量 max_sum,初始化为数组的第一个数,该变量就是最终结果。之后就是从下标为1的位置开始遍历(因为下标为0的无须处理),每次遍历,将前面计算的最大和和该位置上的数字相加得到新的最大和,再将这个新值和旧值比较,将大值赋值给 max_sum,再判断一下 temp_sum 是否小于0,如果小于0则可以直接舍弃(此处的舍弃就是再赋值为0),因为小于0的数加上一个数只会更小。
DP就很简单了,但是DP的重难点就是在找到状态转移方程。(此处不详细介绍DP,大家可以移步谷歌搜索DP,会有大量的dalao讲解DP)。
既然重难点是状态转移方程,那么该题中的状态转移方程是什么呢?
d p ( i ) = { n u m s ( 0 ) , i = 0 m a x { d p ( i − 1 ) + n u m s ( i ) , n u m s ( i ) } , i > 0 dp(i) = \left\{ \begin{aligned} nums(0) & , & i=0 \\ max\lbrace{dp(i-1)+nums(i), nums(i)\rbrace} & , & i>0 \\ \end{aligned} \right. dp(i)={nums(0)max{dp(i−1)+nums(i),nums(i)},,i=0i>0
找到状态转移方程的话那代码就好写了,代码看下面,其实很好理解的。
首先,将最大和初始化为第一个数(当长度为1时也是正确的),之后遍历数组,将前面的最大和和当前值相加,再将结果与当前值进行比较取最大值更新 dp 数组(此处就是状态转移方程中的第二个式子)。
为什么此处就可以更新呢?
仔细想想,当前值加上之前的最大和的和却比当前值小,那可以肯定的就是之前的最大和是一个负数,只有是负数才会使其和变小,所以就可以将其更新为当前值。
分治就比较好理解,但是其实运行时间明显大于前两种方法(在LeetCode上提交我的运行时间内是40ms,是前两种方法的5倍)。
找到中间位置,其结果只有三种可能:一是在左边,二是在右边,三是在中间位置两边。所以我们就先递归左边找到左边的最大值(即第一种可能结果),再递归右边找到右边的最大值(即第二种可能结果),之后再从左边的尾部和右边的首部开始遍历,找出中间位置两边的最大值,其和就是第三种可能结果,最后就是比较这三个值了,返回最大的。
int maxSubArray(vector<int>& nums) {
int max_sum = nums[0];
int temp_sum = max_sum > 0 ? max_sum : 0;
for (int i=1; i<nums.size(); ++i) {
temp_sum += nums[i];
max_sum = temp_sum > max_sum ? temp_sum : max_sum;
temp_sum = temp_sum > 0 ? temp_sum : 0;
}
return max_sum;
}
int maxSubArray(vector<int>& nums) {
int dp[nums.size()];
dp[0] = nums[0];
int ans = dp[0];
for (int i=1; i<nums.size(); ++i) {
dp[i] = max(dp[i-1]+nums[i], nums[i]);
ans = max(ans, dp[i]);
}
return ans;
}
int maxSubArray(vector<int>& nums) {
if (nums.size() == 1) {
return nums[0];
}
vector<int> left_vector(nums.begin(), nums.begin() + nums.size() / 2);
vector<int> right_vector(nums.begin() + nums.size() / 2, nums.end());
int left_max1 = maxSubArray3(left_vector);
int right_max1 = maxSubArray3(right_vector);
int left_max2 = left_vector[left_vector.size() - 1];
int left_max2_temp = left_max2;
for (int i=left_vector.size()-2; i>=0; --i) {
left_max2_temp += left_vector[i];
left_max2 = max(left_max2, left_max2_temp);
}
int right_max2 = right_vector[0];
int right_max2_temp = right_max2;
for (int i=1; i<right_vector.size();++i) {
right_max2_temp += right_vector[i];
right_max2 = max(right_max2, right_max2_temp);
}
if (left_max1 >= right_max1 && left_max1 >= (left_max2+right_max2)) {
return left_max1;
}
if (left_max1 <= right_max1 && right_max1 >= (left_max2+right_max2)) {
return right_max1;
}
return left_max2 + right_max2;
}
如有错误之处,敬请指出!大家共勉!