算法第三章上机实践报告
1.实践报告
1.1问题描述
设计一个O(n^2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
1.2算法描述
求解该问题须记录的数据我们用两个数组(num,D)和两个变量(max,t)表示。
arr[i]:表示输入的n个数组中的第i个;
num[i]:表示以arr[i]为尾元素的单调递增序列的最大值;
D[i]:表示以arr[i]为首元素的序列的最长单调递增子序列;
max:记录填表(num)过程中的最大值;
t:记录max所在元素的下标i。
用动态规划的思想,分为以下四个步骤:
①问题结构分析:该问题考察的是最长单调递增子序列的问题,最长单调递增子序列是由相对较短的单调递增子序列构成,这就印证了最长单调递增子序列与相对较短的单调递增子序列之间可以建立递推关系;
②递推关系建立:见1.3.1;
③自底向上计算:从左到右填表(数组arr和数组D);
④最优方案追踪:遍历数组D。
1.3问题求解
1.3.1根据最优子结构性质,列出递归方程式
首先,从D[1]开始。
当arr[i-1]<arr[i]时,分为两种情况:
①num[i-1]+1<max+1,若arr[i]>arr[t],则num[i]=max+1;若arr[i]<=arr[t],则从i-1开始往前遍历,找到符合条件(arr[i]>arr[k])的最大的num[k],即num[i]=num[k]+1;
②num[i-1]+1>=max+1,num[i]=num[i-1]+1;
当arr[i-1]>=arr[i]时,则从i-2开始往前遍历,找到符合条件(arr[i]>arr[k])的最大的num[k],即num[i]=num[k]+1;
以此类推,不断循环,从左往右填写数组arr和数组D;
最后,遍历数组D,找到其最大值,即为题目所求最长单调递增子序列的长度。
1.3.2给出填表法中表的维度、填表范围和填表顺序
表的维度:数组arr和数组D均为一维数组;
填表范围:数组D为从1到n;数组arr为从j(D数组的下标)到n;
填表顺序:数组arr和数组D均为从左到右的顺序;
1.3.3分析该算法的时间和空间复杂度
时间复杂度:该算法用了两层循环(遍历数组D以及遍历数组arr),所以时间复杂度为O(n^2);
空间复杂度:需要填写两个表(数组arr和数组D)以及两个变量(max和t),所以空间复杂度为O(2n)+O(1)=O(n)。
1.4心得体会
1.4.1本次实践收获
加深了对动态规划算法的理解,能够更加熟练地运用动态规划算法,并且在处理临界条件和特殊情况有了更深入的思考并取得较大的进步。
1.4.2本次实践疑惑
有时候处理数组时可以用写在main函数里,不会出现问题,有时候又必须定义成全局数组才不会出错,感觉不太懂。
处理方法:定义成全局数组就没错了。
2.对动态规划算法的理解和体会
动态规划算法与分治法类似,其基本思想也是将带求解问题分解成若干子问题
但是经分解得到的子问题往往不是互相独立的。不同问题的数目常常有多项式量级。在用分治法求解时,有些子问题被重复计算了许多次。
如何减少子问题的重复计算就是动态规划算法的关键解决思想!