机器学习面试,被问过最多的数据结构类题目是动态规划(Dynamic Programming,即DP)。所以总结一下剑指offer中常见的几种DP题目,供后续的回顾与学习。
首先,DP题目的几种类型为:递推、背包、最长递增子序列、最长公共子序列。
1、递推
典型题目:剑指offer——09 斐波那契数列
理由:因为斐波那契数列的第 F(n) 项的解,包含了子问题 F(n-1) 项的解,即该问题具有“最优子结构”性质;然后要想计算F(n)的解,必须先计算 F(n-1) 和 F(n-2) 的解,这些子问题中包含大量重复计算的过程,所以具有“重叠子问题”的性质;再者,当前值 F(n) 的状态只它前面两个状态(值)有关,每次迭代过程中,只要保留前两个状态,就可以推导出新状态,满足“无后效性”;所以Fibonacci数列问题属于DP问题。
2、背包问题
典型题目:0-1背包问题
思想:用一个二维数组 dp[i][j](含义:在可以任意使用 arr[0...i] 硬币的情况下,组成 j 所需要的最小个数)或者用一维数组 dp[j](含义:硬币之和为金额 j 的方案总数),不过用一维数组相当于只保存当前行(即i行),而 dp[i][j] 则将历史得到的解都保存了下来,两种类型的数组基本思想是一样的。
二维数组的关键递推:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])
一维数组的关键递推:dp[j] = dp[j] + dp[j-w[i]]
相关题目:最少硬币找零问题,正整数之和为SUM的方案数
3、最长递增子序列
思想:把【累积值】与【累计值+当前值】进行比较,将较大值赋给【累积值】;然后将【累积值】与【最大值】进行比较,将较大值赋给【最大值】,即
cur = cur+arr[i] > arr[i] ? cur+arr[i]: arr[i] ; —— ①
max = max > cur ? max: cur ; —— ②
也可以把 ① 进一步化简为: cur = cur > 0 ? cur+arr[i]: arr[i] ;
所以cur保存的是当前累积的较大值,max 中保存的是当前遍历过的最大值,最终 max 即为所求。
4、最长公共子序列
典型题目:求解两个字符创中的最长公共子序列
思想:和前面背包问题实质是一样的,但相比之下:背包问题多了个权重W和价值V,它每次用新数据在其W和V的约束下更新最优解;而寻找最长公共子序列是遇到新数据时加一或不加一来记录最优解,所以该问题是背包问题的简单版。
参考:
https://www.sohu.com/a/153858619_466939 一个入门的漫画讲解
https://blog.csdn.net/na_beginning/article/details/62884939 背包问题详解
https://blog.csdn.net/justdoithai/article/details/51167389 深入理解动态规划DP