🚩传送门:牛客题目

题目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数组。
🍗连续子数组的最大和合集 - 图1

复杂度分析

时间复杂度: 🍗连续子数组的最大和合集 - 图2 ,其中 🍗连续子数组的最大和合集 - 图3 是数组长度。

空间复杂度:🍗连续子数组的最大和合集 - 图4

我的代码

  1. public class Solution {
  2. public int FindGreatestSumOfSubArray(int[] array) {
  3. int res=Integer.MIN_VALUE;
  4. int sum=0;
  5. for(int i=0;i<array.length;i++){
  6. sum+=array[i];
  7. res=Math.max(res,sum);
  8. if(sum<0)sum=0;
  9. }
  10. return res;
  11. }
  12. }

题目2:连续子数组的最大和-II

输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,找到一个具有最大和的连续子数组。

  1. 子数组是连续的,比如[1,3,5,7,9]的子数组有[1,3],[3,5,7]等等,但是[1,3,7]不是子数组
  2. 如果存在多个最大和的连续子数组,那么返回其中长度最长的,该题数据保证这个最长的只存在一个
  3. 该题定义的子数组的最小长度为1,不存在为空的子数组,即不存在[]是某个数组的子数组
  4. 返回的数组不计入空间复杂度计算

解题思路:动态规划

我们其实可以优化,我们会发现只有dp[i]>0的对我们有用,因为只有dp[i] > 0才会对最终的结果答案有正向贡献,即dp[i] + num[i+1] > num[i+1],因此没必要使用dp数组。我们用临时区间坐标记录,当答案大于或者答案相同时,通过答案区间坐标和临时区间坐标的对比,再更新答案区间坐标。

复杂度分析

时间复杂度: 🍗连续子数组的最大和合集 - 图5 ,其中 🍗连续子数组的最大和合集 - 图6 是数组长度。

空间复杂度:🍗连续子数组的最大和合集 - 图7

我的代码

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);    
    }
}