給定乙個整數序列,a0, a1, a2, …… , an(項可以為負數),求其中最大的子串行和。
即輸入一組整數,求出這組數字子串行和中的最大值,只要求出最大子串行的和,不必求出最大值對應的序列。
最大子串行和:整數序列a1, a2,... an (可能有負數),求a1~an的乙個子串行ai~aj,使得ai到aj的和最大。
例如:序列:-2, 11, -4, 13, -5, 2, -5, -3, 12, -9,則最大子串行和為21。
序列:0, -3, 6, 8, -20, 21, 8, -9, 10, -1, 3, 6, 5,則最大子串行和為43。
方法一:
用三層迴圈,想要找到這個子串行,肯定是需要迴圈遍歷,有點類似於氣泡排序的感覺。
所以第一層迴圈確定起點,第二層迴圈確定終點,第三層迴圈在起點和終點之間遍歷。
時間複雜度:o(n^3)
即演算法的執行時間是以輸入長度的立方增長,當輸入長度過長,程式的執行效率將變得越來越大。
void maxsumone(int a, int n)
if (thissum > maxsum)
}} printf("第一種方式求最大子序和為:%d \n",maxsum);
}
方法二:
相當於改進第一種方法,只使用兩層迴圈,就是不用每次都重新加一遍,每次加完比較一遍。
時間複雜度:o(n^2)
演算法的執行時間是以輸入長度的平方增長。
void maxsumtwo(int a, int n)
} printf("第二種方式求最大子序和為:%d \n", maxsum);
}
方法三:
採用遞迴的思想,把序列分成左右兩個序列,分別求兩個序列的最大序列和,這個序列大最大序列的位置只有三種情況:
1、最大序列和完全在左邊部分;
2、最大序列和完全在右邊部分;
3、最大序列和跨越左右兩部分。
所以為了求出結果,可以分別求出左部分的最大序列和、右部分的最大序列和和跨越左右兩部分的最大序列和,然後進行比較,最大的即為所求。
求左半部分的最大子串行和,可把左半部分作為新的輸入序列通過該演算法遞迴求出。右半部分的最大子串行和也同理。
跨越左右兩部分的最大子串行和即為兩者相加。
時間複雜度:o(n logn)
int maxsumthree(int a, int left, int right)
//左右遞迴求出部分序列最大和
int center = (left + right) / 2;
int maxleftsum = maxsumthree(a, left, center);
int maxrightsum = maxsumthree(a, center + 1, right);
//左int maxleftbordersum = 0, leftbordersum = 0;
for (int i = center; i >= left; i--) }
//右int maxrightbordersum = 0, rightbordersum = 0;
for (int i = center + 1; i <= right; i++) }
//跨越兩邊的
int maxleftrightsum = maxleftbordersum + maxrightbordersum;
//求三個方面的最大序列
int maxsubsum = 0;
maxsubsum = maxleftsum > maxrightsum ? maxleftsum : maxrightsum;
maxsubsum = maxsubsum > maxleftrightsum ? maxsubsum : maxleftrightsum;
return maxsubsum;
}
方法四:
設序列為a,長度為n,從a(0)開始求和並記錄最大值,即開始計算a(0) , a(0)+a(1) , a(0)+a(1)+a(2)......,直到出現小於0的停止,若加到a(i)以後求和小於0,便從a(i+1)之後重新求和。
因為a(i-1)一定是大於0的,加上a(i)求和小於0,即a(i)是小於0的,之後求和的序列不必加上這個小於0的和值。
時間複雜度:o(n)
void maxsumfour(int a, int n)
printf("第四種方式求最大子序和為:%d \n", maxsum);
}
最後除錯使用的主程式為:
#include#include//時間複雜度為n**3
void maxsumone(int a, int n)
if (thissum > maxsum)
}} printf("第一種方式求最大子序和為:%d \n",maxsum);
}//時間複雜度為n**2
void maxsumtwo(int a, int n)
} printf("第二種方式求最大子序和為:%d \n", maxsum);
} //遞迴求解(n * logn)
int maxsumthree(int a, int left, int right)
//左右遞迴求出部分序列最大和
int center = (left + right) / 2;
int maxleftsum = maxsumthree(a, left, center);
int maxrightsum = maxsumthree(a, center + 1, right);
//左int maxleftbordersum = 0, leftbordersum = 0;
for (int i = center; i >= left; i--) }
//右int maxrightbordersum = 0, rightbordersum = 0;
for (int i = center + 1; i <= right; i++) }
//跨越兩邊的
int maxleftrightsum = maxleftbordersum + maxrightbordersum;
//求三個方面的最大序列
int maxsubsum = 0;
maxsubsum = maxleftsum > maxrightsum ? maxleftsum : maxrightsum;
maxsubsum = maxsubsum > maxleftrightsum ? maxsubsum : maxleftrightsum;
return maxsubsum;
}//時間複雜度為n
void maxsumfour(int a, int n)
printf("第四種方式求最大子序和為:%d \n", maxsum);
}int main()
; int n1 = sizeof(arr1) / sizeof(arr1[0]);
maxsumone(arr1,n1);
maxsumtwo(arr1,n1);
printf("第三種方式求最大子序和為:%d \n", maxsumthree(arr1, 0, n1));
maxsumfour(arr1, n1);
system("pause");
return 0;
}
其實第乙個和第二個方法是最容易想出來的,但是用來解決例子是沒有問題的,但是放到實際應用中就顯得捉襟見肘了。後面兩種方法比較難理解,但是是一種思想。 和最大子串行
問題描述 第一行輸入乙個正整數n 1 n 100001 第二行輸入n個整數a 0 a 10000 求該組整數子串行最大的和。解決這個問題應該考慮輸入n較大的情況,也就是說,輸入100000個數字判斷它的和最大子串行應當也能很快地算出來。我看過很多求解的 有三重for迴圈的,有兩重for迴圈的,也有使...
最大子串行和
最大子串行是要找出由數組成的一維陣列中和最大的連續子串行。比如的最大子串行就是 它的和是8,達到最大 而 的最大子串行是,它的和是6。找最大子串行的方法很簡單,只要前i項的和還沒有小於0那麼子串行就一直向後擴充套件,否則丟棄之前的子串行開始新的子串行,同時我們要記下各個子串行的和,最後找到和最大的子...
和最大子串行
時間限制 1 sec 記憶體限制 512 mb 提交 3 解決 3 提交 狀態 討論版 對於乙個給定的長度為n的整數序列a,它的 子串行 的定義是 a中非空的一段連續的元素 整數 你要完成的任務是,在所有可能的子串行中,找到乙個子串行,該子串行中所有元素的和是最大的 跟其他所有子串行相比 程式要求你...