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

陣列中最大和的子陣列

題目:

輸入一個整型陣列,資料元素有正數也有負數,求元素組合成連續子陣列之和最大的子陣列,要求時間複雜度為O(n)

例如:

輸入的陣列為1, -2, 3, 10, -4, 7, 2, -5,最大和的連續子陣列為3, 10, -4, 7, 2,其最大和為18

背景:

本題最初為2005年浙江大學計算機系考研題的最後一道程式設計題,在2006年裡包括google在內的很多知名公司都把本題當作面試題。

由於本題在網路中廣為流傳,本題也順利成為2006年程式設計師面試題中經典中的經典。

分析:

如果不考慮時間複雜度,我們可以枚舉出所有子陣列並求出他們的和。不過非常遺憾的是,由於長度為n的陣列有O(n2)個子陣列(即:n + n-1 + ... + 1=n(n+1)/2);而且求一個長度為

n的陣列的和的時間複雜度為O(n)。因此這種思路的時間是O(n3)

很容易理解,當我們加上一個正數時,和會增加;當我們加上一個負數時,和會減少。如果當前得到的和是個負數,那麼這個和在接下來的累加中應該拋棄並重新清零,不然的話這個負數將會減少接下來的和。基於這樣的思路,我們可以寫出如下程式碼。

void MaxSum(int array[], unsigned int len)
{
	if(NULL == array || len <=0){
		return;
	}

	int curSum = 0, maxSum = 0;
	int i = 0;
	for(i=0; i<len; i++){
		curSum += array[i];		// 累加

		if(curSum < 0){			// 當前和小於0,重置為0
			curSum = 0;
		}

		if(curSum > maxSum){	// 當前和大於最大和,則重置最大和
			maxSum = curSum; 
		}
	}

	if(maxSum == 0){			// 最大和依然為0,說明陣列中所有元素都為負值
		maxSum = array[0];
		for(i=1; i<len; i++){
			if(array[i] > maxSum){
				maxSum = array[i];
			}
		}
	}

	printf("maxSum: %d", maxSum);
}

測試陣列:

int array[] = {1, -2, 3, 10, -4, 7, 2, -5};		// 3, 10, -4, 7, 2 = 18
執行結果:


程式碼改進:

有時,需要輸出最大和的子陣列及其開始、結束下標,程式碼如下:

void MaxSum(int array[], unsigned int len)
{
	if(NULL == array || len <=0){
		return;
	}

	int curSum = 0, maxSum = 0;
	int index_start = 0, index_end = 0;		// 初始化子陣列最大和下標
	int i = 0;
	for(i=0; i<len; i++){
		curSum += array[i];		// 累加

		if(curSum < 0){			// 當前和小於0,重置為0
			curSum = 0;
			index_start = i+1;		// 調整子陣列最大和的開始下標
		}

		if(curSum > maxSum){		// 當前和大於最大和,則重置最大和
			maxSum = curSum; 
			index_end = i;			// 調整子陣列最大和的結束下標
		}
	}

	if(maxSum == 0){			// 最大和依然為0,說明陣列中所有元素都為負值
		maxSum = array[0];
		index_start = index_end = 0;				// 初始化子陣列最大和下標
		for(i=1; i<len; i++){
			if(array[i] > maxSum){
				maxSum = array[i];
				index_start = index_end = i;		// 調整子陣列最大和下標
			}
		}
	}

	// 輸出最大和的子陣列及其開始、結束下標
	printf("index_start: %d\nindex_end: %d\n", index_start, index_end);
	for(i=index_start; i<=index_end; i++){
		printf("%d\t", array[i]);
	}

	printf("\n\nmaxSum: %d", maxSum);
}

測試陣列:

int array[] = {1, -2, 3, 10, -4, 7, 2, -5};		// 3, 10, -4, 7, 2 = 18
執行結果:




原始碼

參考推薦: