连续子数组的最大和

175 阅读2分钟

题目描述

输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n).

[1,-2,3,10,-4,7,2,-5]

18

输入的数组为{1,-2,3,10,—4,7,2,一5},和最大的子数组为{3,10,一4,7,2},因此输出为该子数组的和 18。

首先我们来最简单的暴力解法: 时间复杂度是O(N^2),空间复杂度是O(1)

public class Solution {
    int max = Integer.MIN_VALUE;
    
    public int FindGreatestSumOfSubArray(int[] array) {
           //可以用O(N)的时间复杂度解决
           //但如果是用O(N^2)的时间复杂度也是可以的
        //比如暴力解法,用双指针
        for(int i = 0 ; i < array.length; i++)
        {
            int temp = 0;
            for(int j = i; j < array.length; j++)
            {
                temp += array[j];
                max = Math.max(max , temp);
            }
        }
          return max;
    }
}
  • 接下来我们优化处理:

  • 用动态规划来做

  • 时间复杂度是O(N),空间复杂度也是O(N)

public class Solution {
    int max = Integer.MIN_VALUE;
    
    public int FindGreatestSumOfSubArray(int[] array) {
           //那其实这个题,我们还可以用动态规划来做
        //定义一个长度跟数组长度一样长的dp数组,dp[i]代表的是,以array[i]结尾时,最大的子数组和是多少
        int[]dp = new int[array.length];
        dp[0] = array[0];
      
        for(int i = 1; i < array.length; i++)
        {
            if(dp[i - 1] <= 0)
            {
                dp[i] = array[i];
            }
            else
            {
                dp[i] = dp[i - 1] + array[i];
            }
            max = Math.max(max , dp[i]);
        }
        return max;
    }
}
  • 我们还可以更优化
  • 时间复杂度O(N),空间复杂度O(1)
public class Solution {
    int max = Integer.MIN_VALUE;
    
    public int FindGreatestSumOfSubArray(int[] array) {
         //如果是O(N)的时间复杂度,不借助其他空间
        //永远存放之前连续的最大和
        int preSum = 0;
        //如果之前的和小于0,再加上一个小于0的,就更小,所以preSum = current;
        
        //
        for(int i = 0; i < array.length; i++)
        {
            if(preSum < 0)
            {
                preSum = array[i];
            }
            else
            {
                preSum += array[i];
            }
            max = Math.max(max , preSum);
        }
        return max;
    }
}