算法第三章上机实践报告
1. 实践报告任选一题进行分析。内容包括:
1.1 问题描述
设计一个O(n2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
输入格式:
输入有两行: 第一行:n,代表要输入的数列的个数 第二行:n个数,数字之间用空格格开
输出格式:
最长单调递增子序列的长度
1.2 算法描述
需要计算最长子序列,需要以下几个变量:
- n 表示输入的总序列数
- arr[i] 表示以arr[i] 为尾元素的序列
- arr[t] 表示以arr[t] 为头元素的序列
- max 表示 当前 最长 子序列的长度
- length[i] 表示 当前 单调递增序序列的长度
用动态规划的思想进行计算,共有以下几个步骤:
- 问题分析:该问题要求的是最长子序列,每一个最长子序列都是由短的子序列加一个元素构成,故形成递推关系
- 递推关系为:详见1.3.1
- 该序列为从始到末开始计算:从左到右填表(数组arr),并计算当前序列的最长子序列lenth[i]
- 最优结果:便利数组arr[]得到length[i]的最大值max
1.3 问题求解:
1.3.1 根据最优子结构性质,列出递归方程式
当arr[i] > arr[t] && length[i] < length[t] + 1 时:
由arr[i] > arr[t]可知,前大后小(i > t)
由length[i] < length[t] + 1可知, 前一数组当前最长子序列长度小于后一个数组的最长子序列长度
因此,前一数组的最长子序列需要更新+1
由length[i]记录该序列更新后的最长子序列
max记录总遍历过程中的最长子序列,即为所求结果
lenth[i] ={ length[t] + 1 <- if(arr[i] > arr[t]) length[i] <- if(arr[i] <= arr[t]) }
1.3.2 给出填表法中表的维度、填表范围和填表顺序。
表一:arr[ ]
表的维度:数组arr[i]为一维数组
填表范围:【0, n - 1】
填表顺序;从左到右
表二:length[ ]
表的维度:数组length[i]为一维数组
填表范围:【0, n - 1】
填表顺序;从左到右
1.3.3 分析该算法的时间和空间复杂度
时间复杂度:O( n ^2)
解释:该算法使用了两层循环,一层为输入,一层为求结果
空间复杂度:O(2n0 + O(1) = O(n)
解释:需要填写两个表( 数组arr[] 和 length[i] ),以及两个变量( max 和 n )
1.4 心得体会(对本次实践收获及疑惑进行总结)
实践收获:
学会了如何运用动态规划的方法求解问题,加深了对于动态规划方法的理解,更加熟练地设置判断条件和输入范围,在算法学习上再上一层楼!
疑惑:
对于函数如何调用还是不太明白,每次调用函数都会经历报错再修改的过程,目前理解依旧不透彻。
2. 你对动态规划算法的理解和体会
1、动态规划的求解过程中需要将大问题分解为小问题,按照一定的方向进行递归运算
2、递归过程中要进行比较,关键是通过比较得出当前的最优解
3、在计算过程中,要精简计算过程,减少重复计算
将大问题分解成小问题,这些”小问题“会不会被被重复调用,是运用”动态规划“算法的核心因素