编程之美 - 数组最大和的子序列

问题描述:

一个数组有N个元素,求这个数组中子数组的最大和。
要求:

  • 子数组是数组中连续的几个元素
  • 数组的元素包含正数,负数,0

思路: 使用动态规划的方式从第n-1个元素开始,向前累加。 如果
当前值 
大于
当前值+以前和则在
当前和的位置保存
当前值,否则保存
当前值+以前和 sum[n-2] = max(a[n-2],  sum[n-1]+a[n-1]),

程序示例 : getMaxSum()

扩展问题: 如果数组首尾相邻,找到其中一段最大和。

思路:

问题大概存在三种情况

《编程之美 - 数组最大和的子序列》

第一种情况就是普通问题的解, 第二种和第三种是有循环的情形,从头向尾循环和从尾向头循环。

考虑先取得没有循环时的一个最大值,再取得有循环时的最大值,再取他们中的最大值。 在计算循环的情况时,先找方向,确定是情况2,还是情况3。 再按照方向计算出一个循环情况下的最大值。

程序示例 : getMaxSumLoop()

#include <iostream>

using namespace std;

int max(int x, int y)
{
    return (x > y) ? x : y;
}

int getMaxSum(int arr[], int len)
{
    int i = 0, ret = 0, pos_s = 0, pos_e = 0;
    int* start = NULL;
    int* sum_max = NULL;

    if (len == 0)
        return 0;

    start = new int[len];
    sum_max = new int[len];

    start[len-1] = arr[len-1];
    sum_max[len-1] = arr[len-1];
    pos_s = pos_e = len-1;

    for (i = len-2; i>=0; i--)
    {
        start[i] = max(arr[i], arr[i] + start[i+1]);
        sum_max[i] = max(start[i], sum_max[i+1]);

        if (sum_max[i] == start[i])
        {
            if (start[i] == arr[i])
            {
                pos_s = i; pos_e = i;
            }
            else
            {
                pos_s = i;
            }
        }
    }
    ret = sum_max[0];
    delete[] start;
    delete[] sum_max;

    cout << "Max= " << ret << "    Start Pos = " << pos_s << "    End Pos = " << pos_e << endl;
    return ret;
}

int getMaxSumLoop(int arr[], int len)
{
    int i = 0, ret = 0, pos_0 = 0, pos_last = 0;
    int max_0 = 0, max_last = 0, sum_0 = 0, sum_last = 0;
    int M1 = 0, M2 = 0;

    if (len == 0)
        return 0;

    M1 = getMaxSum(arr, len);

    max_0 = arr[0];
    sum_0 = arr[0];
    max_last = arr[len-1];
    sum_last = arr[len-1];
    for (i = 1; i < len; i++)
    {
        sum_0 += arr[i];
        sum_last += arr[len-1-i];
        if (sum_0 >= max_0)
        {
            max_0 = sum_0;
            pos_0 = i;
        }

        if (sum_last >= max_last)
        {
            max_last = sum_last;
            pos_last = len-1-i;
        }
    }

    if (pos_0 >= pos_last)
    {
        if (max_0 > max_last)
        {
            M2 = max_0;
            sum_0 = max_0;
            for (i = len-1; i > pos_0; i--)
            {
                sum_0 += arr[i];
                if (sum_0 >= M2)
                {
                    M2 = sum_0;
                }
            }
        }
        else
        {
            M2 = max_last;
            sum_last = max_last;
            for (i = 0; i < pos_last; i++)
            {
                sum_last += arr[i];
                if (sum_last >= M2)
                {
                    M2 = sum_last;
                }
            }
        }
    }
    else
    {
        M2 = max_0 + max_last;
    }

    if (M1>M2)
        cout << "Max= " << M1 << endl;
    else
        cout << "Max (loop)= " << M2 << endl;

    ret = max(M1, M2);
    return ret;
}


void main()
{
    int test1[] = {1,-2,3,5,-3,2};
    int test2[] = {1,-2,3,5,-1,2};
    int test3[] = {-9,-2,-3,-5,-3};
    int len1 = sizeof(test1)/sizeof(test1[0]);
    int len2 = sizeof(test2)/sizeof(test2[0]);
    int len3 = sizeof(test3)/sizeof(test3[0]);

    getMaxSum(test1, len1);
    getMaxSum(test2, len2);
    getMaxSum(test3, len3);

    cout << "===============================" << endl;

    getMaxSumLoop(test1, len1);
    getMaxSumLoop(test2, len2);
    getMaxSumLoop(test3, len3);

    cin>> len1;
}
    原文作者:zy__
    原文地址: https://blog.csdn.net/wangzhiyu1980/article/details/51392500
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞