求一个数组的子数组的最大和

如题:求一个数组的子数组的最大和,要求O(n)时间复杂度。

由于有了O(n)时间复杂度的限制,所以暴力求解的O(n^2)方法肯定不行。再考虑递归求一个数组a[n]的子数组的最大和,可以分解为a[i]子数组的最大和以及a[n-i-1]之间的某种情况

  • a[n]的子数组最大和等于a[i]子数组的最大和;
  • a[n]的子数组最大和等于a[n-i-1];
  • a[n]的子数组最大和跨a[i]和a[n-i-1];

递归实现的时间复杂度为O(nlg(n))。最后考虑时间复杂度为O(n)的动态规划实现。

/**
 * Created by elvalad on 2014/12/4.
 * 求一个数组的子数组的最大和
 */
import java.util.ArrayList;
import java.util.Scanner;

public class MaxSubArray {
    /* 暴力遍历所有子数组的和 */
    public static int maxSubArray1(ArrayList<Integer> a) {
        int sum = 0;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < a.size(); i++) {
            sum = 0;
            for (int j = i; j < a.size(); j++) {
                sum += a.get(j);
                if (sum > max) {
                    max = sum;
                }
            }
        }
        return max;
    }

    /* 递归实现 */
    public static int maxSubArray2(ArrayList<Integer> a, int low, int high) {
        int max = Integer.MIN_VALUE;
        int max1 = Integer.MIN_VALUE;
        int max2 = Integer.MIN_VALUE;
        int max3 = Integer.MIN_VALUE;
        int max4 = Integer.MIN_VALUE;
        int sum = 0;

        if (low < high) {
            int mid = low + (high - low)/2;
            /* 最大子数组为左半部分的子数组最大值 */
            max1 = maxSubArray2(a, low, mid);
            /* 最大子数组为右半部分的子数组最大值 */
            max2 = maxSubArray2(a, mid + 1, high);
            /* 最大子数组跨越mid元素,所以最大值必定为mid向左的最大值加上mid向右的最大值 */
            for (int i = mid; i >= low; i--) {
                sum += a.get(i);
                if (sum > max3) {
                    max3 = sum;
                }
            }
            sum = 0;
            for (int i = mid + 1; i <= high; i++) {
                sum += a.get(i);
                if (sum > max4) {
                    max4 = sum;
                }
            }
            return Math.max(Math.max(max1, max2), (max3 + max4));
        } else {
            return a.get(0);
        }
    }

    /* 动态规划 */
    public static int maxSubArray3(ArrayList<Integer> a) {
        int max = Integer.MIN_VALUE;
        int sum = 0;

        /* 每个元素更新sum的值,当sum<0时清零,同时如果sum>max时更新max */
        for (int i = 0; i < a.size(); i++) {
            sum += a.get(i);
            if (sum > max) {
                max = sum;
            } else if (sum < 0) {
                sum = 0;
            }
        }
        return max;
    }

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        ArrayList<Integer> array = new ArrayList<Integer>();
        while (scan.hasNext()) {
            array.add(scan.nextInt());
        }
        System.out.println("The max sub array is :" + maxSubArray1(array));
        System.out.println("The max sub array is :" + maxSubArray2(array, 0, array.size()-1));
        System.out.println("The max sub array is :" + maxSubArray3(array));
    }
}
时间: 2024-10-12 09:06:07

求一个数组的子数组的最大和的相关文章

返回一个二维整形数组的子数组的最大和

实验要求:1输入一个二维整形数组,数组中有正数也有负数.2二维数组中连续的一个子矩阵组成一个子数组,每个 子数组都有一个和.求所有子数组的和的最大值.实验思路:          1.首先确定子数组的最大上界,从第一行依次向下,规定最大子数组的范围. 2.确定子数组的行列类型. 3.用一维子数组的方法求出子数组的最大和,求出最大值. 4.最后将子数组的最大上界下降1,再循环.实验代码 #include<iostream>using namespace std;void main (){    

2.14 求数组的子数组之和的最大值

题目:给定一个一维数组,求这个数组的子数组之和的最大值. 最佳方法:动态规划! 一. 可以将一个大问题(N个元素数组)转化为一个较小的问题(N-1个元素数组).. 假设已经知道(A[1],...A[n-1])中最大的子数组的和为:All[1] 并且已经知道(A[1],...A[n-1])中包括A[1]的子数组的最大和为start[1] 所以最终的解All[0] = max(A[0], A[0]+start[1], All[1]) 所以通过DP来求解! 代码如下: #include <iostre

二位数组的子数组最大值

该题是poj的1050号题:http://poj.org/problem?id=1050 同时在<编程之美> 2.15 小节 思想是: 1.把二维降到一维,把 同一列的若干个数的和算出来, 然后从行的角度,变成求一维数组的子数组和的最大值, 一共要计算 (1+n)*n/2 次一维数组的和最大值 2.在求同一列的若干数的和的时候,用辅助数组加快计算: 把第l列中, 第1~k行数的和提前计算好,放到辅助数组 b[k][l]中, 然后求 第l列的 第i行和第j行之间的数的和,就等于 b[i][l]-

《团队开发一(求一个数组的连续的子数组之和的最大值)》

(1)设计思想:一般的,求一个数组的最大子数组之和即是按数组顺序依次让前几个数的和与下一个数进行比较,设一变量来装每次比较后的较大的数,依此进行到数组终端:但是考虑到求的是连续的子数组,则应该想到除了在按顺序上的连续外,还得考虑到末端与首端的连续,所以按数组顺序依次求解得到的未必就是连续的最大的子数组之和,故此必须在此种情况下也求解出最大子数组之和,方法即是同时从数组的两端依次进行求出各自的最大子数组之和,然后在相遇前求和后与之前所求的最大子数组之和依次相比较,取它们中最大的一个作为连续的最大子

【编程之美】求数组的子数组之和的最大值

一个有N个整数元素的一维数组A[0],A[1],......,A[n-1],这个数组当然有很多子数组,那么子数组的最大值是什么呢? 分析与解法 我们先明确题意: 1. 题目说的子数组,是连续的: 2. 题目只需要求和,并不需要返回子数组的具体位置: 3. 数组中的元素是整数,所以数组可能包含有正整数.零.负整数: 4. 子数组不为空. 解法一:枚举 最简单的办法就是枚举所有的i和j,计算sum[i..j] = A[i]+A[i+1]+...+A[j],遍历所有可能的sum[i..j],找到最大值

编程之美之2.14 求数组的子数组之和的最大值

[题目] 一个有N个整数元素的一维数组(A[0],A[1],A[2],...A[n-1]),这个数组中当然有很多子数组,那么子数组之和的最大值是多少? 该子数组是连续的. 我们先来明确一下题意: (1)子数组意味着是连续的. (2)题目只需要求和,并不需要返回子数组的具体位置. (3)数组的元素是整数,所以数组可能包含正整数,负整数或者零. 举几个例子: 数组:[1,-2,3,5,-3,2]返回8 数组:[0,-2,3,5,-1,2]返回9 数组:[-9,-2,-3,-5,-3]返回8 [解法一

编程之美2.14 求数组的子数组之和的最大值

问题描述: 一个有N个整数元素的一维数组(A[0], A[1], A[2],...,A[n-1]),这个数组当然有很多子数组,那么子数组之和的最大值是什么呢? 解法: 1. 暴力解法-------O(N^3) 2. 改进版暴力解法-------O(N^2) *3. 分治算法-------O(NlogN)(暂时未去实现) 4. 数组间关系法-------O(N) 具体思路和代码: 1.暴力解法 思路:Sum[i,...,j]为数组第i个元素到第j个元素的和,遍历所有可能的Sum[i,...,j].

C#中求数组的子数组之和的最大值

<编程之美>183页,问题2.14——求子数组的字数组之和的最大值.(整数数组) 我开始以为可以从数组中随意抽调元素组成子数组,于是就有了一种想法,把最大的元素抽出来,判断是大于0还是小于等于0,如果大于0就对除了这个最大值外剩下的数组部分进行递归: using System; using System.Collections.Generic; using System.Linq; namespace MaxSumSubArray { class Program { static void M

Task 4 求数组的连续子数组的最大和(团队合作)

小组成员:李敏.刘子晗 1.设计思想:由于已经做过这个题目,只要对之前的程序加上相应的测试和约束即可.我们两个人一起商议后,决定了程序的主框架和并列出了最终可以实现的功能.先要定义数组长度和上下限的变量,然后通过if语句对用户所给出的长度和数值进行判断看是否合法,如果不合法要重新输入.最后再加上之前求和的相应代码即可. 2.出现的问题:我们达成协议后,李敏负责编程,我负责测试.开始写程序,在写判断数值是否满足int整型范围的时候出现了错误,我在测试的时候发现她把小于号错写成了大于号,然后加以改正