1.题目
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [0]
输出:0
示例 4:
输入:nums = [-1]
输出:-1
示例 5:
输入:nums = [-100000]
输出:-100000
提示:
- 1 <= nums.length <= 3 * 104
- -105 <= nums[i] <= 105
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
2.答题
思路1(暴力解题)
好久没有碰到能用暴力解的题了,洪荒之力都被压制了,二话不说,直接解题步骤:
- 声明实际最大值临时变量
- 外循环循环数组,声明本次循环中的最大值临时变量
- 内循环从当前位置开始累加,与当前循环最大值比较,大的替换,其他继续循环
- 内循环结束,比较本次循环最大值与实际最大值
- 外循环继续指导结束
class Solution {
public int maxSubArray(int[] nums) {
int max = nums[0];
for (int i = 0; i < nums.length; i++) {
int tmpMax = nums[i];
int sum = tmpMax;
for (int j = i + 1; j < nums.length; j++) {
sum += nums[j];
if (tmpMax < sum) {
tmpMax = sum;
}
}
max = Math.max(max, tmpMax);
}
return max;
}
}
时间复杂度
使用到了两层循环,故为O(n²)
空间复杂度
常量O(1)
提交结果
思路2(贪心)
尝试一下是否可以贪心算法解决:
1.限制值为个数小于n的连续数组,期望值为连续数组的值和。
2.是否可以使用贪心算法:遍历数组,累加数组元素的和,如果加上当前值后,子数组的和为负数(当前值抵消子数组的贡献),那么当前值的贡献为负,直接跳过当前的值,取下一个值为起点。
3.使用例子[-2,1,-3,4,-1,2,1,-5,4]来尝试是否能得出最优解
当前值 | 子数组和 | 是否跳过 | 说明 | 最大值 |
---|---|---|---|---|
-2 | -2 | 是 | 子数组和为负数 | 0 |
1 | 1 | 否 | 1 | |
-3 | -2 | 是 | 子数组和为负数 | 1 |
4 | 4 | 否 | 4 | |
-1 | 3 | 否 | 3 | |
2 | 5 | 否 | 5 | |
1 | 6 | 否 | 6 | |
-5 | 1 | 否 | 6 | |
4 | 5 | 否 | 6 |
最长子序为:[4,-1,2,1],和为6
public int maxSubArray(int[] nums) {
int max = nums[0];
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
if (sum > max) {
max = sum;
}
if (sum <= 0) {
sum = 0;//跳过当前值,从下一个值开始计算
}
}
return max;
}
时间复杂度
使用到了1层循环,故为O(n)
空间复杂度
常量O(1)
提交结果
动态规划适合求最优解的问题,奈何还没有学会,等学会了再来补充