1. 作业题“挖地雷”分析

1.1 递归方程

用动态规划算法可以将问题分解出最优子结构。

dp[i][j]表示把A字符串前i个字符组成的字符串转变为B字符串前j个字符组成的字符串所需的最少的字符操作数

如果A字符串的第i个字符与B字符串的第j个字符串相同,则这个位置不需要操作,所需的操作等于dp[i-1][j-1],否则需要进行修改,操作数就要+1

由于每个位置都可以进行修改删除插入三种操作,因此需要把这三种操作中编辑距离最小的作为dp[i][j]的值

递推公式(代码表示):

if (A[i - 1] == B[j - 1]) // dp矩阵以1开始,字符数组是0开始,因此对应的话要-1
	dp[i][j] = dp[i - 1][j - 1]; // 如果对应的位置相同就不用操作,否则要修改所以要+1
else
	dp[i][j] = dp[i - 1][j - 1] + 1;

//              修改              删除              插入
dp[i][j] = min(dp[i][j], min(dp[i - 1][j] + 1, dp[i][j - 1] + 1));

1.2 填表

表的维度:二维

填表的范围:(len_A和len_B分别为字符串A、B的长度)

i:1 ~ len_A

j:1 ~ len_B

填表顺序:从左至右,自顶向下(i与j的递增方向)

1.2 复杂度分析

时间复杂度:由于填写的是二维表,需要二重循环,所以时间复杂度是O(n^2)

空间复杂度:需要一个二维数组,因而是O(n^2)

2. 动态规划算法理解

动态规划算法最明显的特点就是可以将大问题分解成自问题,利用子问题的最优解进行再度分析,从中选择最优的作为大问题的解决方案,也就是我们说的具有最优子结构性质。很多情况下是因为我们计算大问题的时候会把在小问题已经计算过的结果进行了二次甚至多次计算,所以会导致时间复杂度的增加,而动态规划算法就很好地规避了这种计算过程的冗余,利用“备忘录”的方法把之前计算过的结果记录下来以便之后直接使用,这个做法不仅减少了计算所需的时间,而且使得之后利用子问题的最优解再次选出本问题的最优解提供了数据基础。

所以动态规划就是一个不断利用子最优解得出现最优解的过程,而这个过程我们需要先列出一个递归方程,至于备忘录我们通常是利用一个二维数组进行记录(有时只需要意一维)。解决问题之前先分析出最优子结构,然后列出递归方程,确定好填表的维度、范围和方向,就可以开始一步步由子问题得出本问题的最优结果。

再拿单调递增最长字序列问题当例子,就是用动态规划的思想,利用子问题的最优解求更大一点的子问题。

设一个数组dp[i]用于存放数组中从0到i下标的序列中,最长的递增子序列的长度

双重遍历,如果arr[j]小于arr[i],则dp[i]dp[j]+1dp[i]中较大的那个。即

dp[i] = max{ dp[j]+1, dp[i] }

由于每次重头又遍历了一次,并每次都分析最优解,避免了1 2 3 9 6 7 这样在最大数后面还有2个较小的数可以产生更长递增子序列的情况可能犯的错误。

3. 结对编程情况

这两次状态好点,很快就可以解决问题。

posted on 2020-10-31 17:29  ccqstark  阅读(96)  评论(0)    收藏  举报