持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第22天,点击查看活动详情
题目描述
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
示例1:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
思路分析
- 今天的算法题目是数组类型题目。题目需要求的是所有连续子数组的和的最大值。这里的关键字是“连续子数组”,"和"。通过关键字分析,首先想到可以用滑动窗口的思想来解决问题,由于是做加法运算,动态调整窗口的大小可以解决。
- 除了滑动窗口的思想,我们也可以使用动态规划的方法来解决问题。动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法,题目比较灵活。具体到这个题目,我们首先定义长度为 n 的DP数组。使用DP[i]表示以nums[i]结尾的最大数组和。初始化dp[0] = nums[0]。由于题目给出的数组中,正数,负数都有,因此,我们需要在nums[i], 和 dp[i - 1] + nums[i] 中选取一个最大值。 得出递推方程如下,dp[i] = Math.max(nums[i], dp[i - 1] + nums[i])。然后每次动态更新 ans 即可。
- 具体实现代码如下,供参考。
通过代码
class Solution {
public int maxSubArray(int[] nums) {
int ans = Integer.MIN_VALUE;
int n = nums.length;
int[] dp = new int[n + 1];
dp[0] = nums[0];
for (int i = 1; i < n; i++) {
dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]);
ans = Math.max(dp[i], ans);
}
ans = Math.max(dp[0], ans);
return ans;
}
}
总结
- 上述算法的时间复杂度是O(n),空间复杂度是O(n)
- 普通DP通过之后,我们再次分析代码,发现dp[i], 只和dp[i-1]有关,因此可以再次优化数组为变量,动态更新即可。空间复杂度可以降低为O(1),使代码更加简洁。
- 坚持算法每日一题,加油!我会继续更新,也欢迎算法爱好者一起交流学习。