题目:
求一组整数数组中的连续子序列和的最大值;如: 4 5 -3 10 -7 3 最大的连续子序列的和为 16 (4+5+(-3)+10)程序从test.txt中读取数组,屏幕输出最大的和。
思路:
最开始是最普通的思路,begin和end两次遍历寻找最大和,这个方法是o(n^2)级。后来尝试(在同学肯定的告诉我有n级别算法之后才果断去尝试)用n级别算法解决,最终考虑和一些可以限制begin的条件,感觉这些条件应当适用:在最大和子序列的和为正数的前提下,1以最大和子序列的开头为开头的最大和子序列的任意子序列之和必为正数2最大和子序列的开头的前一项必为负数,或这个开头就是整个数列的开头 。依次可节省遍历begin的时间,达成o(n)级别算法。
此外还有一件事就是关于文件输入。最开始还以为需要以字符串形式输入数字字符然后通过atoi函数转换为数字(事实上在这份代码中还是这么做的),在上交代码之后才发现有一位同学尝试直接使用fscanf成功,只要以%d格式读取,编译器会自动识别数字。这里是可以改进的地方。
方案:
第一种方案(n级别):从0起至n-1遍历end并计算总和,当当前总和小于0时重置begin并将总和清零,表示数组并未开始记录,当当前和大于最大值时候记录当前和为最大值,遍历一遍后输出
第二种方案(n2级别):从0起至n-1遍历begin,对应每一个begin从begin起至n-1遍历end,计算总和,记录最大总和,输出。
代码:
1 //04.求一组整数数组中的连续子序列和的最大值;如: 4 5 -3 10 -7 3 最大的连续子序列的和为 16 (4+5+(-3)+10) 2 //程序从test.txt中读取数组,屏幕输出最大的和。 3 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 const int MAX_COUNT=100; 10 const int MAX_LEN=5; 11 12 int ArrayFileInput(int **array); 13 void ArrayPrint(int *array,int len); 14 int BiggestSum(int *array,int len); 15 16 int main() 17 { 18 int *array=NULL; 19 int len=ArrayFileInput(&array); 20 printf("The array is:\n"); 21 ArrayPrint(array,len); 22 printf("\nThe biggest sum is:%d",BiggestSum(array,len)); 23 return 0; 24 } 25 26 int ArrayFileInput(int **a_ptr) 27 { 28 FILE *fp; 29 if((fp=fopen("test.txt","r+"))==NULL)//打开文件 30 { 31 printf("Open error!\n"); 32 return 0; 33 } 34 while(fgetc(fp)!='{')//找到数组开头 35 ; 36 *a_ptr=malloc(sizeof(int)*MAX_COUNT);//存储用数组 37 memset(*a_ptr,0,sizeof(int)*MAX_COUNT); 38 char temp_c;//临时字符 39 int i=0,iarray=0;//两个迭代器 40 char str[MAX_LEN];//临时字符串 41 while((temp_c=fgetc(fp))!='}')//循环到数组结尾 42 { 43 if(temp_c!=' ')//正在输入当前数 44 str[i++]=temp_c; 45 else//当前数输入完毕 46 { 47 str[i]='\0';//字符串结尾 48 i=0;//字符串迭代器置零 49 (*a_ptr)[iarray++]=atoi(str);//字符串转数字后存储到数组 50 // memset(str,0,MAX_LEN);//清空临时字符串 51 } 52 } 53 str[i]='\0'; 54 (*a_ptr)[iarray++]=atoi(str); 55 return iarray; 56 } 57 58 void ArrayPrint(int *array,int len) 59 { 60 int i; 61 for(i=0;i<=len-1;++i) 62 printf("%3d",array[i]); 63 } 64 65 int BiggestSum(int *array,int len) 66 { 67 #if 0 68 //思路:在最大和子序列的和为正数的前提下, 69 //1以最大和子序列的开头为开头的最大和子序列的任意子序列之和必为正数 70 //2最大和子序列的开头的前一项必为负数,或这个开头就是整个数列的开头 71 //依此两条规则可节省遍历开头的时间,o(n)级算法 72 int current_begin=-1,current_end=0,current_sum=0,max_begin=0,max_end=0,max_sum=0,max_single_number=0; 73 for(;current_end<=len-1;++current_end) 74 { 75 printf("For test:%d\n",array[current_end]); 76 current_sum+=array[current_end];//当前数列总和加当前值 77 if(array[current_end]>array[max_single_number])//记录最大值 78 max_single_number=current_end;//一旦全数列均为负数,则输出这个最大值 79 if(current_sum<=0)//当前数列总和小于0 80 { 81 //printf("\n=====Clear Test=====\n"); 82 // printf("Begin:%d,End:%d\n",array[current_begin],array[current_end]); 83 // printf("Sum:%d",current_sum); 84 // printf("\n=====Clear Over====="); 85 current_begin=-1;//清除当前序列 86 current_sum=0;//总和清0,重新找当前数列头 87 } 88 else 89 { 90 if(current_begin==-1)//当前数列还未开始 91 current_begin=current_end;//开始 92 if(current_sum>max_sum)//当前数列总和大于已记录最大数列总和 93 { 94 max_begin=current_begin; 95 max_end=current_end; 96 max_sum=current_sum; 97 //printf("\n=====MAX Test=====\n"); 98 // printf("Begin:%d,End:%d\n",array[max_begin],array[max_end]); 99 // printf("Sum:%d",max_sum); 100 // printf("\n=====MAX Over====="); 101 } 102 } 103 } 104 printf("\nResult:\n"); 105 if(array[max_single_number]<0)//说明整个数列就是一条负数 106 { 107 printf("%3d",array[max_single_number]); 108 return array[max_single_number];//返回最大值即可 109 } 110 else 111 { 112 int i; 113 for(i=max_begin;i<=max_end;++i) 114 printf("%3d",array[i]); 115 return max_sum; 116 } 117 #else 118 //思路:begin从头到尾遍历一遍,对应每个begin,end从begin到尾遍历一遍 119 //途中计算sum,记录max_sum的起始点,最终输出 120 //最直接的方法(还有个二货版o(n^3)就当不存在了),o(n^2) 121 int current_begin,current_end,current_sum=0,max_begin,max_end,max_sum=array[0]; 122 for(current_begin=0;current_begin<=len-1;++current_begin) 123 { 124 for(current_end=current_begin;current_end<=len-1;++current_end) 125 { 126 current_sum+=array[current_end]; 127 if(current_sum>max_sum) 128 { 129 max_sum=current_sum; 130 max_begin=current_begin; 131 max_end=current_end; 132 } 133 } 134 current_sum=0; 135 } 136 printf("\nResult:\n"); 137 int i; 138 for(i=max_begin;i<=max_end;++i) 139 printf("%3d",array[i]); 140 return max_sum; 141 #endif 142 }
浙公网安备 33010602011771号