1. 程式人生 > >求子陣列的最大和

求子陣列的最大和

輸入一個整形陣列,數組裡有正數也有負數。
陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。
求所有子陣列的和的最大值。要求時間複雜度為O(n)。

例如輸入的陣列為1, -2, 3, 10, -4, 7, 2, -5,和最大的子陣列為3, 10, -4, 7, 2,
因此輸出為該子陣列的和18。

方法一、窮舉法

     列舉所有的連續陣列。列舉方法,首先可以選擇在陣列的任意位置開始,變數i。然後,選擇在位置變數i後的最終位置,變數j。最後,對位置i和位置j之間的所有元素進行相加。這樣就列舉了所有的連續陣列。三層迴圈,時間複雜度為O(N3)

int maxArray2(int *pArray,int nsize)
{
	int sum=0;
	int maxsum=-10000000;
	for(int i=0;i<nsize;++i)//可以在任意位置開始
	{
		for(int j=i;j<nsize;++j)//結束的位置只能在i或i後
		{
			for(int k=i;k<=j;++k)//對位置i和位置j之間的元素進行相加
			{
				sum=sum+pArray[k];
			}

			
			//如果這個連續陣列的和比sum大,則記錄
			if(maxsum<sum)//
				maxsum=sum;
			//計算下一個連續陣列的和前需清零
			sum=0;
		}

	}
	return maxsum;
}


二、DP方法

     其實對於這個問題,可以劃分為兩個子問題。

(1)從哪個位置開始加

(2)加多少個元素

         對於第一個問題,我們看看陣列1, -2, 3, 10, -4, 7, 2, -5,如果從第一個元素開始加,第一個元素和第二個元素的和為1+2=-1,第二個元素是負的也不合適。因為如果最大的連續陣列包含第一個和第二元素或者包含第二個元素,我們可以從最大的連續陣列中,找出更大連續陣列,排除第一個和第二個元素或者排除第二個元素就可以了。

     對於第二個問題,我們可以通過設定變數解決,我們可以一直加,記錄下最大的maxsum即可。

從這兩個思路應該能比較好的理解下面的這個演算法。這也有些分治的思想在裡面,最大的連續陣列到底在哪個部分,在1還是在-2, 3, 10, -4, 7, 2, -5中,在1,-2中,還是在3, 10, -4, 7, 2, -5中。

int maxArray(int *pArray,int nsize)
{
	int sum=0;
	int maxsum=-10000000;
	for(int i=0;i<nsize;++i)
	{
		sum=sum+pArray[i];
		
		//記錄下最大的sum
		if(maxsum<sum)
			maxsum=sum;

		//如果sum<0要從新位置開始
		if(sum<0)
			sum=0;

	}
	return maxsum;
}