携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
一、题目
LeetCode 最大子数组和
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 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 <= nums.length <= 105
-104 <= nums[i] <= 104
二、题解
给定一个整数的数组,要求最大的子数组的和,子数组是原数组中连续的一段子序列,所以最少含有一个元素,数组的元素值为整数,但是可能会有负数。
方法一
简单的容易想到暴力循环数组元素,计算每一个子数组的和,最后返回最大的和,如果数组元素数量小的情况下可以使用,但是元素数量比较大的时候计算过程就可能超时,太暴力了。对此可以用动态规划来解决,首先需要定义一个和原数组同等大小dp数组,那么dp[i]就表示以nums[i]结尾的子数组最大的和,然后遍历数组计算,返回最后的计算结果即可。初始的话对于nums的第一个元素nums[i]来说其最大值就是自身元素值,因为一个元素也是一个子数组,所以dp[0] = nums[0]。对于其余元素,如果选择该元素来组成子数组的话,那么最大的子数组和就是以前一个元素结尾的子数组之和加上本身元素和即dp[i] = dp[i - 1] + nums[i];如果不选择该元素与前面元素组合成子数组,那么最大的元素和就是该元素本身的值即dp[i] = nums[i],而要取得最大的子数组和就获取两种选择中结果大的一种。对于dp数组每次计算我们只用到了dp[i - 1],所以为了优化空间可以直接使用一个变量来代替dp数组来计算也是可以的。
三、代码
方法一 Java代码
class Solution {
public int maxSubArray(int[] nums) {
int dp = 0;
int maxSum = nums[0];
for (int num : nums) {
dp = Math.max(dp + num, num);
maxSum = Math.max(maxSum, dp);
}
return maxSum;
}
}
时间复杂度:O(n),需要遍历一次数组元素来计算。
空间复杂度:O(1),只使用了常数的空间。