最大和连续子数组

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhufenghao/article/details/70544156

题目

对于一个整数数组,求其连续子数组的最大和。

  • 测试输入
    7
    -2 5 3 -6 4 -8 6
  • 测试输出
    8

分析

可以从后向前考虑问题。数组 array[i] i=0n1 ,定义 total[i] 表示前 i 个元素中连续子数组的最大和,如果子数组不以 array[i] 结尾,则 total[i]=total[i1] ;而如果子数组以 array[i] 结尾,可知 array[i1] array[i2] 也一定被选中,一直到某个元素截止。由此可由动态规划来求解,但是和一般的动态规划有区别。因为截止元素未知,我们不知道当前 total[i] 是从哪个元素开始的子数组最大和。实际上我们并不用知道开始元素,只需要维护一个变量 tail[i] ,它表示以 array[i] 结尾的子数组最大和,如果子数组加上 array[i] 才有最大和,则 tail[i]=tail[i1]+array[i] ;而如果子数组加上 array[i] 其和反而更小,说明当前子数组应该放弃 array[i] ,考虑到子数组必须连续,所以当前子数组结束, array[i] 就成为下一段新子数组的开始元素, tail[i]=array[i] 。递归式为

{tail[i]total[i]==max(array[i], tail[i1]+array[i])max(total[i1], tail[i])

空间优化

由递归式可以看出,只需要遍历一遍就可以得到,因此时间复杂度为 O(n) 。而 tail[i] total[i] 也只和 i1 状态有关,故可以只设置为两个整数即可,空间可以优化到 O(1)

代码

import java.util.Scanner;

public class MaxSum {
    static int solution(int[] array) {
        int n = array.length;
        int[] tail = new int[n];
        int[] total = new int[n];
        tail[0] = total[0] = array[0];
        for (int i = 1; i < array.length; i++) {
            tail[i] = Math.max(array[i], tail[i - 1] + array[i]);
            total[i] = Math.max(total[i - 1], tail[i]);
        }
        return total[n - 1];
    }

    static int solution2(int[] array) {
        int tail = array[0];
        int total = array[0];
        for (int i = 1; i < array.length; i++) {
            tail = Math.max(array[i], tail + array[i]);
            total = Math.max(total, tail);
        }
        return total;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] array = new int[n];
        for (int i = 0; i < n; i++) {
            array[i] = sc.nextInt();
        }
        System.out.println(solution(array));
    }
}

猜你喜欢

转载自blog.csdn.net/zhufenghao/article/details/70544156