最大子序列乘积----DP求解

  问题起源于《数据结构与算法分析-C语言描述》一书中的习题2.12。

  存在序列A(a1,a2,......,a),(在此仅讨论序列A中元素均为整数的情况)

  问:给出有效的算法求解最大子序列乘积。

  一看此题,容易想到的是穷举所有的可能的子序列,求乘积后去最大值,代码如下。

 1 int  MaxProduct(int a[], int len)
 2 {
 3       int Max = a[0];
 4       for(int i = 0; i < len; ++i)
 5       {
 6               int   thisMax = 1;
 7               for(int j = i;  j < len; ++j)
 8               {
 9                       thisMax *= a[j];
10                       Max = Max<thisMax ? thisMax:Max;
11                }
12         }
13          
14         return Max;    
15 }                    
View Code

  此算法的复杂度容易计算得O(n2)。

  根据书中对最大子序列和问题的线性算法求解,进一步探索对该问题的线性求解得可能性。

  同样的,从问题的最终解的形式出发,假设序列A最大乘积的子序列为(ai,ai+1,....aj)。

  由此假设P(k)为以ak结尾的子序列的最大乘积,N(k)为以ak结尾的子序列的最小乘积。

  定义递推公式如下:

          若 ak > 0;  P(k) = ak * P(k-1),  N(k) = ak * N(k-1);

            ak = 0;  P(k) = N(k) = 0;

            ak < 0;  P(k) = ak * N(k-1),  N(k) = ak * P(k-1);

  代码实现如下:

 1 int MaxProduct(int a[], int len)
 2 {
 3     int Max = a[0];
 4     int ThisMax = 0, ThisMin = 0;
 5 
 6     for(int i = 0; i < len; ++i)
 7     {
 8         if(0 == a[i])
 9         {
10             ThisMax = 0;
11             ThisMin = 0;
12 
13         }
14         else if(a[i] > 0)
15         {
16             ThisMax = ThisMax ? ThisMax*a[i] : a[i];
17             ThisMin = ThisMin ? ThisMin*a[i] : ThisMin;
18         }
19         else if(a[i] < 0)
20         {
21             int tmp = ThisMax;
22             ThisMax = ThisMin ? ThisMin*a[i] : 0;
23             ThisMin = tmp ? a[i]*tmp : a[i];
24         }
25 
26          Max = Max>ThisMax?Max:ThisMax;
27     }
28 
29     return Max;
30 }
View Code

  容易计算得到该算法计算复杂度为O(n)。

posted @ 2015-05-24 00:50  eagleliwx  阅读(322)  评论(0编辑  收藏  举报