给定一组数据: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; } }
下面给出算法:
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); }这个算法的巧妙之处就在于计算lmax和rmax之处,计算lmax是从m开始到low结束,计算rmax是从m+1开始,在high结束。
最后一种方法就是使用动态规划了,相信很多人能给出此种算法。直接给出代码:
#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); }