第一章:基本概念
给定N个整数的序列{A1,A2,...,AN},求最大的子列和 。
算法一:暴力法找出所有子列和,时间复杂度O(N^3)
#include<stdio.h>
#include<string.h>
int maxnum(int A[], int n);
int main() {
int A[10] = { 1,2,3,4,-3,4,-9,4,7 };
int n = 10;
int p;
p=maxnum(A, n);
printf("%d", p);
return 0;
}
//最大子列和的暴力求解方法
int maxnum(int A[], int n) {
int i, j, k;
int thisnum;
int maxnum=0;
for (i = 0;i < n;i++) { /*i是子列的左端*/
for (j = i;j < n;j++) { /*j是子列的右端*/
thisnum = 0; /*A[i]到A[j]的子列和*/
for (k = i;k <= j;k++)
thisnum += A[k];
if (thisnum > maxnum)
maxnum = thisnum;
}
}
return maxnum;
}
算法二:暴力法基础上提升,时间复杂度O(N^2)
//此处省略的代码在上面
int maxnum(int A[], int n) {
int i, j, k;
int thisnum;
int maxnum=0;
for (i = 0;i < n;i++) { /*i是子列的左端*/
thisnum = 0;
for (j = i;j < n;j++) { /*j是子列的右端*/
thisnum += A[j]; /*对于相同的i,不同的j,只需要在前一次的基础上加下一个元素*/
if (thisnum > maxnum) {
maxnum = thisnum;
}
}
}
return maxnum;
}
当出现时间复杂度为O(N^2)的时候,程序员就会思考将时间复杂度减小到O(NlogN)
算法3:分而治之,时间复杂度O(NlogN),将复杂的问题分开解决最后合并,时间复杂度的计算方法可以由递推得到
#include<stdio.h>
#include<string.h>
int max3(int a, int b, int c);
int maxnum(int A[], int n);
int maxfenzhi(int A[], int n);
int main() {
int A[10] = { 1,2,3,4,-3,4,-9,4,7 };
int n = 10;
int p;
p=maxfenzhi(A, n);
printf("%d", p);
return 0;
}
int max3(int a, int b, int c) {
return a > b ? a > c ? a : c : b > c ? b : c;
/*这个式子是简略形式,(a > b ? (a > c ? a : c ): (b > c ? b : c))*/
}
int divideandconquer(int List[], int left, int right) {
int maxleft, maxright; /*存放左右子列的和*/
int maxleftborder, maxrightborder; /*存放跨界的结果*/
int leftborder, rightborder;
int center, i;
if (left == right) {
/*递归的终止条件,此时子列只有一个数字*/
if (List[left] > 0)
return List[left];
else
return 0;
}
/*分而治之中的‘分’*/
center = (left + right) / 2; /*找到中分点*/
/*递归求两边子列的最大和*/
maxleft = divideandconquer(List, left, center);
maxright = divideandconquer(List, center+1, right);
/*下面求跨分界线的最大子列和*/
maxleftborder = 0;
leftborder = 0;
for (i = center;i >= left;i--) {
/*从中线向左侧扫描*/
leftborder += List[i];
if (leftborder > maxleftborder)
maxleftborder = leftborder;
}/*左侧扫描结束*/
maxrightborder = 0;
rightborder = 0;
for (i = center + 1;i <=right;i++) {
/*从中线向右侧扫描*/
leftborder += List[i];
if (leftborder > maxleftborder)
maxleftborder = leftborder;
}/*右侧扫描结束*/
/*下面是分而治之中的‘治’*/
return max3(maxleft, maxright, maxleftborder + maxrightborder);
}
int maxfenzhi(int A[], int n) {
return divideandconquer(A, 0, n - 1);
}
算法4:在线处理算法,时间复杂度为O(N),比上面的都要快!想一下这也是最快的算法了,因为处理这种问题必须要全部看一遍数据,当然越快的算法有时候看起来不那么好理解。
#include<stdio.h>
#include<string.h>
int maxzaixian(int A[], int n);
int main() {
int A[10] = { 1,2,3,4,-3,4,-9,4,7 };
int n = 10;
int p;
p=maxzaixian(A, n);
printf("%d", p);
return 0;
}
int maxzaixian(int A[], int n) {
int maxnum = 0;
int thisnum = 0;
for (int i = 0;i < n;i++)
{
thisnum += A[i];
if (thisnum > maxnum) {
maxnum = thisnum;
}
if (thisnum < 0)
{
thisnum = 0;
}
}
return maxnum;
}
第一章的算法就是这样了,陆续会继续出以后的章节以及补充练习等等。