Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Example 1:

Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

Example 2:

Input: nums = [1]
Output: 1

Example 3:

Input: nums = [0]
Output: 0

Example 4:

Input: nums = [-1]
Output: -1

Example 5:

Input: nums = [-100000]
Output: -100000

Constraints:

  • 1 <= nums.length <= 3 * 104
  • -105 <= nums[i] <= 105

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.

最大子数组。

题意是给一个数组,请找出其sum值最大的子数组,只要求找到这个sum值即可。

思路是动态规划。设 dp[i] 是以 nums[i] 结尾的子数组的和。扫描数组,当遇到某个数i的时候,需要判断 dp[i - 1] 是否小于0。如果小于0,nums[i] + dp[i - 1] 的结果只会拖累 dp[i];如果大于0,可以将 dp[i] = dp[i - 1] + nums[i] 。最后return最大的 dp[i] 即可。

时间O(n)

空间O(n)

JavaScript实现

 1 /**
 2  * @param {number[]} nums
 3  * @return {number}
 4  */
 5 var maxSubArray = function(nums) {
 6     let dp = new Array(nums.length);
 7     dp[0] = nums[0];
 8     let res = nums[0];
 9     for (let i = 1; i < nums.length; i++) {
10         dp[i] = dp[i - 1] < 0 ? nums[i] : dp[i - 1] + nums[i];
11         res = Math.max(res, dp[i]);
12     }
13     return res;
14 };

 

Java实现

 1 class Solution {
 2     public int maxSubArray(int[] nums) {
 3         int[] dp = new int[nums.length];
 4         dp[0] = nums[0];
 5         int res = nums[0];
 6         for (int i = 1; i < nums.length; i++) {
 7             dp[i] = nums[i] + (dp[i - 1] < 0 ? 0 : dp[i - 1]);
 8             res = Math.max(res, dp[i]);
 9         }
10         return res;
11     }
12 }

 

这种DP的思路也有节省空间的做法,其实我们并不一定需要知道每个dp[i]值的大小,我们只需要在遍历过程中记录一下最大的dp值即可。思路也是很类似,如果之前的值prev小于0,一定会拖累cur的,所以cur = nums[i];反之如果prev大于0,cur就变为nums[i] + prev。每次用res记录一下当前的子数组的最大值之后,就可以把cur赋给prev以达到节省空间的目的了。

时间O(n)

空间O(1)

 1 class Solution {
 2     public int maxSubArray(int[] nums) {
 3         int prev = nums[0];
 4         int cur = nums[0];
 5         int res = nums[0];
 6         for (int i = 1; i < nums.length; i++) {
 7             if (prev < 0) {
 8                 cur = nums[i];
 9             } else {
10                 cur = prev + nums[i];
11             }
12             res = Math.max(res, cur);
13             prev = cur;
14         }
15         return res;
16     }
17 }

 

还有另外一种思路,类似DP的做法,是去求局部最大和整体最大。设两个变量sum和res,sum记录当遍历到nums[i]的时候,sum + nums[i]是否对值的扩大有帮助;res记录最大的sum值。

时间O(n)

空间O(1)

Java实现

 1 class Solution {
 2     public int maxSubArray(int[] nums) {
 3         int res = nums[0];
 4         int sum = nums[0];
 5         for (int i = 1; i < nums.length; i++) {
 6             sum = Math.max(nums[i], sum + nums[i]);
 7             res = Math.max(res, sum);
 8         }
 9         return res;
10     }
11 }

 

JavaScript实现

 1 /**
 2  * @param {number[]} nums
 3  * @return {number}
 4  */
 5 var maxSubArray = function(nums) {
 6     let res = nums[0];
 7     let sum = nums[0];
 8     for (let i = 1; i < nums.length; i++) {
 9         sum = Math.max(nums[i], sum + nums[i]);
10         res = Math.max(res, sum);
11     }
12     return res;
13 };

 

相关题目

53. Maximum Subarray

152. Maximum Product Subarray

918. Maximum Sum Circular Subarray

978. Longest Turbulent Subarray

LeetCode 题目总结