陣列連續子序列的最大的和;四種演算法,四種時間複雜度
阿新 • • 發佈:2019-02-19
給定一組資料:31, -41, 59, 26, -53, 58, 97, -93, -23, 84。要求找到這組資料中連和最大的子序列,相信很多人都看過這個演算法,能夠直接給出線性時間複雜度的解法。但是還是有其他解法的,而且是循序漸進的,從O(n^3), O(n^2), O(n*logn)到O(n)。
在開始演算法之前要進行一下約定,如果當前輸入的都是負數的時候,綜合最大的子序列是空的,總和為0.
第一種方法就是brute-force解法,就是對滿足所有的0<=i < j < n的組合(i,j)進行迭代,對於每個整數對都要計算a[i,j]的總和,這個演算法有個特點,也就是造成時間複雜度很高的缺點,對於每次計算的結果沒有記錄,只是簡單的將此次計算的結果和上次計算的結果進行比較,求得當前最大值後,就給扔掉了。下面給出演算法:
- current_max = 0;
- sum = 0;
- for(i = 0; i < n; i++) {
- for(j = i; j < n; j++) {
- sum = 0;
- for(k = i; k <= j; k++)
- sum += a[k];
- if(sum > current_max)
- current_max = sum;
- }
- }
很清楚的可以看出,對i和j的操作過程中,只是對當前和與上次的和做簡單的比較,之後就扔棄了。想一想,可不可以這樣做,對於特定的i,遍歷所有可行的j值,記錄此次(i,j)的操作,對於(i,j+1)的操作可以在(i,j)所得和的基礎上簡單的加a[j+1]就可以了。
下面給出演算法:
- current_max = 0;
- for(i = 0; i < n; i++) {
- sum = 0;
- for(j = i; j < n; j++) {
- sum += a[j];
- if(sum > current_max)
- current_max = sum;
- }
- }
同時,這個問題還可以用分治演算法來解決,可能會有疑問,因為分治演算法是用來解決子問題之間沒有聯絡的問題的。而求連續子序列和最大值得問題更多的和動態規劃相關,因為用動態規劃很容易解決這個問題。但是分治也可以,這種演算法很巧妙,巧妙的讓人不可思議。給出演算法程式碼:
- #include<stdio.h>
- int max(int a, int b, int c) {
- if(a > b) {
- if(a > c) {
- return a;
- } else {
- return c;
- }
- } else {
- if(b > c) {
- return b;
- } else {
- return c;
- }
- }
- }
- int get_max(int *a, int low, int high) {
- int m = (low + high) / 2;
- int i;
- int sum, lmax, rmax;
- if(low > high)
- return 0;
- if(low == high)
- return a[low] > 0 ? a[low] : 0;
- sum = lmax = 0;
- for(i = m; i >= low; i--){
- sum += a[i];
- if(sum > lmax) {
- lmax = sum;
- }
- }
- sum = rmax = 0;
- for(i = m + 1; i <= high; i++) {
- sum += a[i];
- if(sum > rmax) {
- rmax = sum;
- }
- }
- return max(lmax + rmax, get_max(a, low, m), get_max(a, m + 1, high));
- }
- void main() {
- int a[] = {31, -41, 59, 26, -53, 58, 97, -93, -23, 84};
- int n = sizeof(a) / sizeof(int);
- int result = get_max(a, 0, n - 1);
- printf("max_sum = %d\n", result);
- }
最後一種方法就是使用動態規劃了,相信很多人能給出此種演算法。直接給出程式碼:
- #include<stdio.h>
- int get_max2(int *a, int n) {
- int current_max = a[0];
- int final_max = a[0];
- int i;
- for(i = 1; i < n; i++) {
- if(current_max + a[i] > 0) {
- current_max += a[i];
- } else {
- current_max = 0;
- }
- if(current_max > final_max) {
- final_max = current_max;
- }
- }
- return final_max;
- }
- void main() {
- int a[] = {31, -41, 59, 26, -53, 58, 97, -93, -23, 84};
- int n = sizeof(a) / sizeof(int);
- int rst = get_max2(a, n);
- printf("max_sum = %d\n", rst);
- }