算法第2章实践报告
- 实践题目名称:7-1 maximum number in a unimodal array
- 问题描述:
从一个由n个(1<= n <= 10000)不同元素组成的数组中找到最大数(该数组元素特点是:从小单调递增直到出现最大值,然后再逐渐递减),同时要保证算法的时间复杂度是O(log n)
- 算法描述:
先用一个数组array[n]来存储n个数据,然后根据二分法求解出最大元素值。
设数组中第一个元素为left,最后一个元素为right,则middle=(left+right)/2
利用array[middle]与它旁边元素进行比较(在这里选定和array[middle+1]进行比较),从而逐步缩小范围:
①当left=right时,直接返回结果array[left],即:
if(left==right)
return array[left];
② 当array[middle]>array[middle+1]时,说明最大值在(left,middle)区间内,所以我们令right=middle,将区间向左缩小,即:
if(array[middle]>array[middle+1])
return BinSearch(array,left,middle);
③当array[middle]<array[middle+1]时,说明最大值在(middle+1,right)区间内,所以我们令left=middle+1,将区间向右缩小,即:
if(array[middle]<array[middle+1])
return BinSearch(array,middle+1,right);
- 算法时间及空间复杂度分析(要有分析过程):
①时间复杂度:
在长度为n的数组中,每进行一次二分搜索,待搜索数组的大小就要减少一半。而在最坏情况下,有n*(1/2)^x=1(最后只剩下一个数),可算得时间复杂度为O(log n)
②空间复杂度:
由于该算法没有借助辅助数组,只在原数组中进行操作,与问题规模n大小无关,所以它的空间复杂度是O(1)
- 心得体会(对本次实践收获及疑惑进行总结):
我在这次实践课上收获颇多,和搭档一起合作完成了2道编程题,对二分法的思想以及应用也有了更加深入的体会。有点遗憾的是,我们小组没能很好适应老师要求的合作模式(一个人打代码,另一个人看并且给予建议)。一开始彼此打自己的代码,注释解释之类的都自己完成,以至于出现错误的时候无法及时解决,白白浪费时间。不过要在别人注视下完成代码,对我来说也算是一种挑战,希望自己以后能够尽快客服,不断提升自己的编程水平。
- 分治法的个人体会和思考
分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,在保证子问题互相独立且与原问题相同的前提下,递归解决子问题,最终合并得到答案。总的来说就是通过“分解问题,求解问题和合并问题”三个步骤来处理原问题,有时还能降低问题的时间复杂度。
但是对于某些问题来说,使用分治法会显得繁琐,甚至是难以实现,就如书本上的Strassen矩阵乘法。在对变形之前的子问题使用分治法,时间复杂度依旧是O(n^3)。直到Strassen提出一种全新算法才解决这份难题,把时间复杂度降为O(n^2.81)。可惜对子问题的变形这一步骤又过于困难,对我来说又很难实现。不过对于我这个初学者来说,真正困扰我的而是递归范围的判断,有时总是写错范围或者写漏符号,导致结果出错,希望自己在接下来的学习当中可以尽快改正这一点。