🚩传送门:牛客题目
题目1:连续子数组的最大和-I
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)
。
示例1:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4] 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解题思路:动态规划
我们其实可以优化,我们会发现只有dp[i]>0
的对我们有用,因为只有dp[i]>0
才会对最终的结果答案有正向贡献,即dp[i]+num[i+1]>num[i+1]
,因此没必要使用dp
数组。
复杂度分析
时间复杂度: ,其中
是数组长度。
空间复杂度:
我的代码
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
int res=Integer.MIN_VALUE;
int sum=0;
for(int i=0;i<array.length;i++){
sum+=array[i];
res=Math.max(res,sum);
if(sum<0)sum=0;
}
return res;
}
}
题目2:连续子数组的最大和-II
输入一个长度为n
的整型数组array
,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组。
- 子数组是连续的,比如
[1,3,5,7,9]
的子数组有[1,3],[3,5,7]等等,但是[1,3,7]
不是子数组 - 如果存在多个最大和的连续子数组,那么返回其中长度最长的,该题数据保证这个最长的只存在一个
- 该题定义的子数组的最小长度为
1
,不存在为空的子数组,即不存在[]
是某个数组的子数组 - 返回的数组不计入空间复杂度计算
解题思路:动态规划
我们其实可以优化,我们会发现只有dp[i]>0
的对我们有用,因为只有dp[i] > 0
才会对最终的结果答案有正向贡献,即dp[i] + num[i+1] > num[i+1]
,因此没必要使用dp
数组。我们用临时区间坐标记录,当答案大于或者答案相同时,通过答案区间坐标和临时区间坐标的对比,再更新答案区间坐标。
复杂度分析
时间复杂度: ,其中
是数组长度。
空间复杂度:
我的代码
public class Solution {
public int[] FindGreatestSumOfSubArray (int[] array) {
// write code here
int n=array.length;
int res_start=0; // 结果集区间起始坐标
int res_end=n; // 结果集区间终止坐标
int start=0; // 临时区间起始坐标
int end=0; // 临时区间终止坐标
int sum=0; // 临时区间和
int res=Integer.MIN_VALUE; // 结果集
for(int i = 0;i < n;i++){
end = i; // 记录临时区间的终止坐标
sum += array[i];
// 如果求和结果大了,则记录答案值并刷新新的结果集区间坐标
if(sum > res){
res_start = start;
res_end = end;
res = sum;
}
// 如果求和结果相同,则对比谁的区间长度更长,并刷新新的结果集区间坐标
else if(res==sum){
// 判断新区间是否长度更长
if(i-start > res_end-res_start){
res_end = end;
res_start = start;
}
}
// 当前的区间和小于零,说明对于后面是负反馈,需要重置信息
if(sum < 0){
sum = 0;
start = i + 1; // 尝试新起点
}
}
// 拷贝新的结果集
return Arrays.copyOfRange(array,res_start,res_end + 1);
}
}