续 常用算法(一)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
五,动态规划
适用条件
- 问题的解可由子问题的解组合而成;
- 子问题有重叠,会被重复求解;
- 无后效性。某阶段的状态一旦确定,则此后过程的演变不再受此前各种状态及决策的影响。例如钢条切割问题。当n=3的最佳方案求出之后,计算n=4时的最佳方案时不会再影响到n=3的最佳方案的结果了。又例如最大子数组的和问题,当P[i]求出之后,在计算P[i+1]时,不会改变P[i]的值。
- 经常用于求最优解,或求完成某种任务的方法个数
解题步骤
- 求出递推式(求递推式可以采用自顶向下的选择法,也可采用自底向上的递推法。)
- 选择法(推荐,更直观):主问题上做一个选择,问题变化成一个或多个子问题。常用于问题能够被化为多个子问题的情况:如干活(连续两天干活后必须休息一天)。又如best time to buy and sell a stock IV
- 递推法:假设子问题已经被解决,主问题在子问题的基础上如何解:常用于问题能够被化为一个子问题的情况。(最大子数组的和)
- 第二步:自底向上,用一个数组保存子问题的求解结果。或自顶向下,用cache保存结果
动态规划的变形
有些问题难以做到直接使用动态规划求解,需要一个转换。例如最大子数组的和问题。如果希望直接用动态规划,令P[i]为子数组0到i的最大子数组的和,则难以推导出P[i+1]和P[i]的关系。所以,令P[i]为子数组0到i的,以i为右边界的最大子数组的和,则可以容易推导出P[i+1]与P[i]的关系。
- Maximum sub array
- Longest palindrome string
- Unique Binary search tree
有些题中,为了求得最终结果,需要规划多个递推式。
- Maximum product subarray 此题以i为右边界的子数组的最大乘积需要依赖于以i-1为右边界的子数组的最大(正数)和最小乘积(负数)。负数x负数=正数
- Best time to buy and sell stock IV 两递推式:前i天最多允许j次交易的全局最优解g[i][j]和前i天最多允许j次交易,且最后一次交易发生在第i天的局部最优解l[i][j]
六,贪心法
适用条件
- 可用动态规划解的问题。
- 寻优问题
- 当前问题做出一个最优选择之后,转化为唯一的一个子问题,然后递归求解
- 动态规划中,做出的每一个选择,依赖于子问题的解。贪心则不依赖子问题的解,它只是当前最优的方案。例如Jump Game。如从正向开始求解,令P[i]为从i处到目的地所需要的最少步数,则这是个动态规划的方案。因为从i出走出的第一步到哪个位置依赖于子问题P[j] ( j是>i且i能到达的所有位置)的值。如从终点反向开始求解,第一步为能到达终点的最远的一个位置,然后递归求解,则是贪心方案,因为当前选择并未依赖任何子问题的解。事实上,子问题尚未求解。
解题步骤
自顶向下,用递归的方式
前提
需要证明这个贪心的选择能够得到最优解
题例
- Jump game
- Meeting room
七,排序应用
全排序
预排序,应用于数组,和双指针算法一起工作
- Container with most water
- 2 sum
强制排序,适用于排除重复解
- Permutation II
- Subsets II
预排序,可以将o(n2)的算法降为o(nlogn)
- Merge Intervals
部分排序
分割,应用于数组,适用于不需要全部排序,然后需要找到某个位置的场合
- Find k biggest number
基数排序及其它,适用于时间复杂度要求较高的场合 o(n).
- Maximum Gap