导航

编程题目记录131220:第四题

Posted on 2013-12-20 19:21  生存在夹缝中  阅读(181)  评论(0)    收藏  举报

题目:

  求一组整数数组中的连续子序列和的最大值;如: 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 }