0053.Maximum-Subarray

最大子数组和

1. 题目

1.1. 描述

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组是数组中的一个连续部分。

1.2. 示例

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]
输出:1

示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

1.3. 提示

  • 1 <= nums.length <= $10^5$
  • -$10^4$ <= nums[i] <= $10^4$

1.4. 进阶

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解

2. 思路

2.1. 卡丹算法

维基百科

  • 定义的ans变量返回最终值,tempSum变量得到以该位置为结束的最大子数列和该位置数值的更大值
  • 时间复杂度为O(n),空间复杂度为O(1)

2.2. 分治法

  • 数组一分为二,寻找左右两边的最大子数组和,层层二分,找到左/中/右的最大值
  • 时间复杂度为O(nlogn),空间复杂度为O(logn)

3. 代码

3.1. C++

3.1.1. 卡丹算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int ans = nums[0];
int len = nums.size();
int tempSum = 0;
for (int i = 0; i < len; i++)
{
tempSum = max(tempSum+nums[i],nums[i]);
ans = max(tempSum,ans);
}
return ans;

}
};

3.1.2. 分治法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
int maxSubArray(vector<int>& nums) {
return dfs(nums,0,nums.size()-1);
}
int dfs(vector<int>& nums,int left,int right){
if(left>=right) return nums[left];
int leftSum = 0, rightSum = 0;
int mid = left+(right-left)/2;
for (int i = mid-1,tempSum = 0;i>=left;i--)
{
tempSum+=nums[i];
leftSum=max(leftSum,tempSum);
}
for (int i = mid+1,tempSum = 0;i<=right;i++)
{
tempSum+=nums[i];
rightSum=max(rightSum,tempSum);
}
return max({dfs(nums,left,mid-1),dfs(nums,mid+1,right),leftSum+nums[mid]+rightSum});
}
};

3.2. Java

3.2.1. 卡丹算法

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public int maxSubArray(int[] nums) {
int tempSum = 0;
int ans = nums[0];
for (int num : nums) {
tempSum = Math.max(tempSum+num, num);
ans = Math.max(tempSum,ans);
}
return ans;
}
}

3.2.2. 分治法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public int maxSubArray(int[] nums) {
return dfs(nums,0,nums.length-1);
}
private int dfs(int[] nums,int left,int right){
if(left>=right) return nums[left];
int leftSum = 0,rightSum = 0;
int mid = left+(right-left)/2;
for (int i = mid-1,tempSum = 0; i >=left; i--) {
tempSum+=nums[i];
leftSum=Math.max(leftSum, tempSum);
}
for (int i = mid+1,tempSum=0; i <= right; i++) {
tempSum+=nums[i];
rightSum=Math.max(rightSum, tempSum);
}
return Math.max(Math.max(dfs(nums,left,mid-1),dfs(nums,mid+1,right)),leftSum+nums[mid]+rightSum);
}
}
本文结束  感谢您的阅读
  • 本文作者: Wang Ting
  • 本文链接: /zh-CN/2017/07/17/0053-Maximum-Subarray/
  • 发布时间: 2017-07-17 22:04
  • 更新时间: 2025-01-08 15:38
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!