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

      1 #include <iostream>
      2 #include <ctime>
      3 using namespace std;
      4 
      5 /*    最大子序列和问题求解
      6  *    给定数A1, A2, ..., An,求第i个到第j个累积和的最大值。
      7  *    如果所有整数均为负数,则最大子序列和为0
      8  */
      9 
     10 /*
     11  *    方法1:穷举式地尝试所有的可能
     12  */
     13 int maxSubsequenceSum_1(const int A[], int N) {
     14     int thisSum, maxSum, i, j, k;
     15     maxSum = 0;
     16     for(i = 0; i < N; i++)
     17         for(j = i; j < N; j++) {
     18             thisSum = 0;
     19             for(k = i; k <= j; k++)        //    出现大量不必要的计算,被过分地耗时
     20                 thisSum += A[k];
     21             if(thisSum > maxSum)
     22                 maxSum = thisSum;
     23         }
     24     return maxSum;
     25 }    //时间复杂度为O(N3)
     26 
     27 int maxSubsequenceSum_2(const int A[], int N) {
     28     int thisSum, maxSum, i, j;
     29     maxSum = 0;
     30     for(i = 0; i < N; i++) {
     31         thisSum = 0;
     32         for(j = i; j < N; j++) {
     33             thisSum += A[j];
     34             if(thisSum > maxSum)
     35                 maxSum = thisSum;
     36         }
     37     }
     38     return maxSum;
     39 }    //时间复杂度O(N2)
     40 
     41 int max3(int a, int b, int c) {
     42     int max;
     43     max = a;
     44     if(b > max)
     45         max = b;
     46     if(c > max)
     47         max = c;
     48     return max;
     49 }
     50 
     51 /*    分治(divide-and-conquer)策略 - 
     52  *    “分”指把问题分成两个大致相等的子问题,然后递归地对它们求解
     53  *    “治”指将两个子问题的解合并到一起并可能再做些少量的附加工作,最后得到整个问题的解
     54  */
     55 int maxSubSum(const int A[], int left, int right) {
     56     int maxLeftSum, maxRightSum;
     57     int maxLeftBorderSum, maxRightBorderSum;
     58     int leftBorderSum, rightBorderSum;
     59     int center, i;
     60 
     61     if(left == right) {    //    只有一个元素时
     62         if(A[left] > 0)
     63             return A[left];
     64         else
     65             return 0;
     66     }
     67 
     68     //    最大子序列和出现在数据的左半部或者右半部,递归求解
     69     center = (left + right) / 2;
     70     maxLeftSum = maxSubSum(A, left, center);
     71     maxRightSum = maxSubSum(A, center+1, right);
     72 
     73     //    最大子序列和占据左右两半部分
     74     //    求出前半部分的最大和(包含前半部分的最后一个元素)
     75     maxLeftBorderSum = 0; leftBorderSum = 0;
     76     for(i = center; i >= left; i--) {
     77         leftBorderSum += A[i];
     78         if(leftBorderSum > maxLeftBorderSum)
     79             maxLeftBorderSum = leftBorderSum;
     80     }
     81     //    求出后半部分的最大和(包含后半部分的第一个元素)
     82     maxRightBorderSum = 0; rightBorderSum = 0;
     83     for(i=center+1; i <= right; i++) {
     84         rightBorderSum += A[i];
     85         if(rightBorderSum > maxRightBorderSum)
     86             maxRightBorderSum = rightBorderSum;
     87     }
     88 
     89     return max3(maxLeftSum, maxRightSum, maxLeftBorderSum+maxRightBorderSum);
     90 }
     91 
     92 int maxSubsequenceSum_3(const int A[], int N) {
     93     return maxSubSum(A, 0, N-1);
     94 }    //    时间复杂度O(NlogN)
     95 
     96 /*    优点:只对数据进行一次扫描,一旦A[i]被读入并被处理,它就不再需要被记忆
     97  *    此外,在任意时刻,算法都能对它已经读入的数据给出序列问题的正确答案 - 联机算法
     98  */
     99 int maxSubsequenceSum_4(int A[], int N) {
    100     int thisSum, maxSum, j;
    101     thisSum = maxSum = 0;
    102     for(j = 0; j < N; j++) {
    103         thisSum += A[j];
    104         if(thisSum > maxSum)
    105             maxSum = thisSum;
    106         else if(thisSum < 0)
    107             thisSum = 0;
    108     }
    109     return maxSum;
    110 }    //    时间复杂度O(N)
    111 
    112 int main() {
    113     time_t start, end;
    114     int A[] = {4, -3, 5, -2, -1, 2, 6, -2, 10, 9, -5, -2, 10, 2, -5, 3};
    115     int maxSum;
    116 
    117     start = clock();
    118     maxSum = maxSubsequenceSum_1(A, 16);
    119     cout << maxSum << endl;
    120     end = clock();
    121     cout << 1000.0 * (end - start) / CLOCKS_PER_SEC << endl;    //执行maxSubsequenceSum_1所花费的时间
    122 
    123     start = clock();
    124     maxSum = maxSubsequenceSum_2(A, 16);
    125     cout << maxSum << endl;
    126     end = clock();
    127     cout << 1000.0 * (end - start) / CLOCKS_PER_SEC << endl;
    128 
    129     start = clock();
    130     maxSum = maxSubsequenceSum_3(A, 16);
    131     cout << maxSum << endl;
    132     end = clock();
    133     cout << 1000.0 * (end - start) / CLOCKS_PER_SEC << endl;
    134 
    135     start = clock();
    136     maxSum = maxSubsequenceSum_4(A, 16);
    137     cout << maxSum << endl;
    138     end = clock();
    139     cout << 1000.0 * (end - start) / CLOCKS_PER_SEC << endl;
    140 
    141     return 0;
    142 }

      参考书籍《数据结构与算法分析:C语言描述》

  • 相关阅读:
    步步为营 .NET 设计模式学习笔记 四、Singleton(单例模式)
    步步为营 .NET 设计模式学习笔记 九、Command(命令模式)
    步步为营 .NET 设计模式学习笔记 十八、Template(模板模式)
    步步为营 .NET 代码重构学习笔记 七
    步步为营 .NET 设计模式学习笔记 十九、Chain of Responsibility(职责链模式)
    步步为营 .NET 设计模式学习笔记 二十二、Memento(备望录模式)
    步步为营 .NET 设计模式学习笔记 十四、Decorator(装饰模式)
    步步为营 .NET 代码重构学习 十一
    步步为营 .NET 设计模式学习笔记 一、开篇(设计模式之泡妞二十三招)
    步步为营 .NET 设计模式学习笔记 七、Proxy(代理模式)
  • 原文地址:https://www.cnblogs.com/wjq-Law/p/5668212.html
Copyright © 2011-2022 走看看