我选择的书是代码大全
一. 程序的架构和思路:
朴素算法就是一个三重循环,但是当n极大的时候,时间会爆表。
#include<iostream> #include<cstdio> using namespace std; int max(int x,int y) { if (x > y) return x; else return y; } int main() { int n,a[10010]; int i,j,k,ans,temp; while (scanf("%d",&n) != EOF) { for (i = 0;i < n;i++) scanf("%d",&a[i]); ans = a[0];//确定下界 for (i = 0;i < n;i++) for (j = i;j < n;j++) { temp = 0; for (k = i;k <= j;k++) temp = temp + a[k];//累加 ans = max(ans,temp); } printf("%d ",ans); } return 0; }
此算法容易理解,时间复杂度为O(n^3)。
继续想其他优化,其实这个可以看做两个求和问题,求i到j的和可以看做1到j的和减去1到i的和,于是可用树状数组优化。
等等...不会这么复杂吧...
利用树状数组优化可将时间复杂度降至O(n^2*(logn)^2),还是有点大,而且代码量太长,效率不够高。
回看第一种方法,其做了很多冗余的操作,例如,先计算i到j,之后继续计算i到j+1,于是可从上一步的值过渡到下一步,因此也就可以消掉一重循环。
#include<iostream> #include<cstdio> using namespace std; int max(int x,int y) { if (x > y) return x; else return y; } int main() { int n,a[10010]; int i,j,ans,sum; while (scanf("%d",&n) != EOF) { for (i = 0;i < n;i++) scanf("%d",&a[i]); ans = a[0];//确定下界 for (i = 0;i < n;i++) { sum = 0; for (j = i;j < n;j++) { sum = sum + a[j];//从上一步继续加 ans = max(ans,sum); } } printf("%d ",ans); } return 0; }
由此可见,此算法时间复杂度为O(n^2),但是n极大的时候依旧会爆表,所以,我觉得能继续优化。
如果我们不需要知道最大子序列位置的话,i循环似乎就没有用了。
若i到j为最大子序列,那么a[i]不可能为负,因为若a[i]为负,a[i+1]为正,则i+1到j为最大。
所以我们可以这么认为,若枚举到i到j阶段时,此阶段和为0,则可舍去,最大子序列必不包含此阶段。
不过需要注意的是,若a数组全为负,则程序输出为0,于是需要加个一重循环特判下界。
#include<iostream> #include<cstdio> using namespace std; int max(int x,int y) { if (x > y) return x; else return y; } int main() { int n,a[10010]; int i,ans,sum; while (scanf("%d",&n) != EOF) { for (i = 0;i < n;i++) scanf("%d",&a[i]); ans = a[0]; for (i = 1;i < n;i++) ans = max(ans,a[i]);//特判下界 sum = 0;ans = 0; for (i = 0;i < n;i++) { sum = sum + a[i]; if (sum > ans) ans = sum; else if (sum < 0) sum = 0;//若小于0则舍去 } printf("%d ",ans); } return 0; }
由此可见,此算法时间复杂度为O(n),应该能够应对大部分数据了。
二. 写这个程序的心得:
心得算不上,说说优化的想法吧。
首先需要写出程序的朴素算法,不管时间复杂度有多高。
然后需要列出自己所做的无用功,看代码,是否可以通过上一步得出这一步,这是动态规划的思想:用空间换时间。
也可以尝试利用分治的思想,将n优化为logn(很遗憾这题我没想明白怎么分治...)。
最重要的是要细心,看自己是否理解错了题意,多做了工作,是否可以省略掉。
三. 程序时间消耗与开发效率分析:
这点做得不够好,因为我不会用程序的计时功能...
不过可以根据程序本身算出时间复杂度,自然,3个程序的时间复杂度是递减序列,但是开发时间却是递增序列。
还是秉承着越好的算法需要越长的时间去构思0.0
四. 程序运行截图:
其实说实话这个没有太大意义...3个程序运用的数据相同,自然截图也是相同的...
五. 感想与不足:
此课程感觉是算法设计的进阶,由于我算法学的还算不错,因此对于目前的作业来说还是能玩得转的。
但是,不同于算法的是,我需要提交程序运行时间...
争取在下次作业提交前学会怎么计时吧...