求連續向量的最大子和問題(掃描算法)

問題來自《編程珠璣》這本書,我記得之前考研的時候模擬題目中也有過相似的題目,當時書上的代碼特別簡單易懂,不過也有些時日了,當時是怎樣寫的基本也就忘了。算法

如今回過頭來在看看這個問題。編程


1.  問題描述數據結構

問題來自一維的模式識別,問題的輸入是具備n個浮點數的向量x,輸出是輸入向量的任何連續子向量的最大和。例如,若是輸入向量包含下面10個元素:spa

31code

-41orm

59ci

26io

-53table

58class

97

-93

-23

84

那麼該程序的輸出爲x[2..6]的總和,即187。當全部數都是正數時,問題很容易解決,此時最大的子向量就是整個輸入向量。當輸入中含有負數時麻煩就來了:是否應該包含某個負數並指望旁邊的整數會彌補它呢?

2.  簡單算法

完成該任務的淺顯程序就是對全部知足0<=i<=j<n的(i,j)整數對進行迭代。對每一個整數對,程序都要計算x[ij]的總和,並檢驗總和是否大於迄今爲止的最大總和。該算法的僞代碼以下所示:

maxsofar = 0

for i = [0,n)

     for j = [i,n)

         sum = 0

         for k = [i,j]

              sum += x[k]

              /* sum is sum of x[i..j] */

              maxsofar = max(maxsofar, sum)

     這段代碼簡潔、直觀而且易於理解。不幸的是,程序的運行速度也很慢。

3.  兩個平方算法

有兩個算法能夠明顯地提升第一個算法的速度,其中一個是比較明顯可想的,而另一個則不那麼明顯,它們的時間複雜度都是平方時間(對於輸入規模n來講,須要執行O(n^2 )步)。

能夠注意到,x[i..j]的總和與前面已計算出的總和(x[i..j-1]的總和)密切相關。利用這一關係便可獲得算法。僞碼以下:

maxsofar = 0

for i = [0,n)

     sum = 0

     for j = [i,n)

         sum += x[j]

         /* sum is sum of x[i..j] */

          maxsofar = max(maxsofar, sum)

     另外一個平方算法是經過訪問在外循環執行以前就已構建的數據結構的方式在內循環中計算總和。cumarr中的第i個元素包含x[0..i]中各個數的累加和,因此x[i..j]中各個數的總和能夠經過計算cumarr[j]-cumarr[i-1]獲得。從而獲得以下所示的僞碼:

cumarr[-1] = 0

for i = [0,n)

     cumarr[i] = cumarr[i-1] + x[i]

maxsofar = 0

for i = [0,n)

     for j = [i,n)

     sum = cumarr[j] - cumarr[i-1]

     /* sum is sum of x[i..j] */

     maxsofar = max(maxsofar, sum)

下面開始貼上代碼

#include<stdio.h>

void main()
{
	int i,end_max,sum;
	int a[10]={31,-41,59,26,-93,58,97,-93,-23,84};

	
	end_max=a[0];
	sum=0;
	for(i=1;i<10;i++)
	{

		if(end_max>0)
		{
			if(end_max>sum)
				sum=end_max;
			end_max+=a[i];
		}
		else 
			end_max=a[i];
	}
	
	printf("%d",sum);
}
相關文章
相關標籤/搜索