zoukankan      html  css  js  c++  java
  • 算法 :最大子序列和问题

    一 写在开头

    何为最大子序列和问题?最大子序列和问题可以描述如下:给定一个整数序列A1, A2, ..., AN(可能有负数),试求其存在的一子序列AI, AJ, ...,AM所能达到的最大值(I, J,...,M不一定是相邻的,只要满足I <= J <= ... <= M即可)(为方便起见,如果所有整数均为负数,则其最大子序列和为0)。

    1.1 本文内容

    求解最大子序列和的几种算法。

    二 算法一

    算法一是相当直观的枚举算法,其时间复杂度为O(N ^ 3)。主要由算法中的三重for循环达成。其实现如下:

     1 int
     2 MaxSubsequenceSum(const int a[], int n)
     3 {
     4     int thisSum, maxSum, i, j, k;
     5 
     6     maxSum = 0;
     7     for (i = 0; i < n; i++)
     8         for (j = i; j < n; j++)
     9         {
    10             thisSum = 0;
    11             for (k = i; k <= j; k++)
    12                 thisSum += a[k];
    13 
    14             if (thisSum > maxSum)
    15                 maxSum = thisSum;
    16         }
    17     return maxSum;
    18 }

    三 算法二

    算法二在算法一的基础上去掉了第三重for循环,因此其时间复杂度为O(N ^ 2)。其实现如下:

     1 int
     2 MaxSubsequenceSum(const int a[], int n)
     3 {
     4     int thisSum, maxSum, i, j;
     5 
     6     maxSum = 0;
     7     for (i = 0; i < n; i++)
     8     {
     9         thisSum = 0;
    10         for (j = i; j < n; j++)
    11         {
    12             thisSum += a[j];
    13             if (thisSum > maxSum)
    14                 maxSum = thisSum;
    15         }
    16     }
    17 }

    四 算法三

    算法三是个递归算法。其每次都将区间一分为二,然后再分别对左右区间递归地进行求解。因为,拥有最大和的子序列要么完全处于左区间,要么完全处于右区间,要么就是左区间的子序列加上右区间的子序列以拼凑成一个和更大的子序列。该算法时间复杂度为O(NlogN),其实现如下:

     1 int
     2 MaxSubsequenceSum(const int a[], int left, int right)
     3 {
     4     int maxLeftSum, maxRightSum;
     5     int maxLeftBorderSum, maxRightBorderSum;
     6     int leftBorderSum, rightBorderSum;
     7     int center, i;
     8 
     9     /* base case */
    10     if (left == right)
    11         if (a[left] > 0)
    12             return a[left];
    13         else
    14             return 0;
    15 
    16     center = (left + right) / 2;
    17     maxLeftSum = MaxSequenceSum(a, left, center);
    18     maxRightSum = MaxSequenceSum(a, center + 1, right);
    19 
    20     maxLeftBorderSum = leftBorderSum = 0;
    21     for (i = center; i >= left; i--)
    22     {
    23         leftBorderSum += a[i];
    24         if (leftBorderSum > maxLeftBorderSum)
    25             maxLeftBorderSum = leftBorderSum;
    26     }
    27 
    28     maxRightBorderSum = rightBorderSum = 0;
    29     for (i = center + 1; i <= right; i++)
    30     {
    31         rightBorderSum += a[i];
    32         if (rightBorderSum > maxRightBorderSum)
    33             maxRightBorderSum = rightBorderSum;
    34     }
    35 
    36     return MAX3(maxLeftSum, maxRightSum, maxLeftSum + maxRightSum);
    37 }

    五 算法四

    算法四比较巧妙,而且时间复杂度只有O(N),优于上面的三种算法,其实现如下:

     1 int
     2 MaxSubsequenceSum(const int a[], int n)
     3 {
     4     int thisSum, maxSum, i;
     5 
     6     thisSum = maxSum = 0;
     7     for (i = 0; i < n; i++)
     8     {
     9         thisSum += a[i];
    10         if (thisSum > maxSum)
    11             maxSum = thisSum;
    12         else if (thisSum < 0)
    13             thisSum = 0;
    14     }
    15     return maxSum;
    16 }

    六 参考资料

    1. 《数据结构与算法分析:C语言描述》

  • 相关阅读:
    gcc 使用中常用的参数及命令
    Android build system & Android.mk 规范
    ndkgdb对java/native code联合调试
    Android NDK开发指南(一) Application.mk文件
    字符编码知识:Unicode、UTF8、ASCII、GB2312等编码 及 转换
    C & C++ 中值得注意的编译,链接,调试,错误及其原因
    JNI 调用规范
    Graphic 矢量图形的区域填充与缠绕规则
    Android NDK开发指南(二)Android.mk文件
    JNI 之二 :java & c/c++ 相互通信及调用
  • 原文地址:https://www.cnblogs.com/laizhenghong2012/p/9511449.html
Copyright © 2011-2022 走看看