leetcode-剑指offer 42-连续子数组的最大和
[博客链接]
[题目描述
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
示例1:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
提示:
1 <= arr.length <= 10^5
-100 <= arr[i] <= 100
注意:本题与主站 53 题相同:https://leetcode-cn.com/problems/maximum-subarray/
Related Topics 数组 分治 动态规划
👍 313 👎 0
[题目链接]
[github地址]
[思路介绍]
思路一:前缀和+暴力法
- sum[j]-sum[i-1] = a[i]+...+a[j]
- TLE了
public int maxSubArray(int[] nums) {
int[] sums = new int[nums.length + 1];
int sum = 0,max =Integer.MIN_VALUE;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
sums[i + 1] = sum;
}
for (int i = 1; i < sums.length; i++) {
for (int j = i; j < sums.length; j++) {
max = Math.max(sums[j] - sums[i-1],max);
}
}
return max;
}
时间复杂度O()
思路二:一维动态规划
-
首先可以确定一个dp思路
-
dp[i] 表示以第i个元素为结尾的最大子元素和
-
j-i号元素的元素和 dp[i] = Math.max(dp[i-1]+ nums[i], nums[i])
-
否则dp[i] = dp[i-1]
public int maxSubArray(int[] nums) {
int[] dp = new int[nums.length + 1];
int ans = nums[0];
dp[1] = nums[0];
for (int i = 1; i < nums.length; i++) {
//表示前i-1的最大子元素和以及边界到当前位置的元素和
dp[i + 1] = Math.max(dp[i] + nums[i], nums[i]);
ans = Math.max(ans, dp[i + 1]);
}
return ans;
}
时间复杂度O(n)
思路三:滚动数组
- 根据上述dp方程可以发现,当前的求值只与当前元素之和上一个元素有关
- 所以可使用滚动数组进行优化
public int maxSubArray(int[] nums) {
int ans = nums[0], pre = nums[0];
for (int i = 1; i < nums.length; i++) {
//表示前i-1的最大子元素和以及边界到当前位置的元素和
pre = Math.max(pre+ nums[i], nums[i]);
ans = Math.max(ans, pre);
}
return ans;
}
时间复杂度O(n)
思路四:线段树+分治 这思路有点复杂 好饿晚点再补