动态规划
基础知识
动态规划是一种思想,因此这里主要讲解动态规划相关的习题及应用。
区间调度问题
1.无权区间调度问题
对于该问题,{b, e, h}是最大互相兼容的任务集合,这里需要使用贪心算法。
贪心算法:总是做出当前最优的选择,并不总能得到最优解,但是它是最简单最容易实现的算法。
无权区间调度问题贪心算法:先将任务以某种顺序排序,再按顺序挑选互相兼容的任务。
对于该问题,需要按照结束时间排序,时间复杂度是O(nlogn)
2.带权区间调度问题
动态规划四步骤:
- 确定状态:先按任务结束时间排序,定义状态OPT(j)为任务{1, 2, …, j}的最大权重,如
- 状态转移方程
- 初始条件和边界情况
- 确定计算顺序
在动态规划的实现中,可以使用自底向上(一般是for循环,易于理解)或者自顶向下(使用递归方式,可能可以节省一些不必要的计算)的方式实现。
补:在计算P(j)的时候,时间复杂度是O(n),需要将区间按照开始时间排序,和按照结束时间排序的结果,然后使用双指针计算P(j)即可。
背包问题
对于该题,按照贪心算法行不通,需要使用动态规划解决。
动态规划步骤:
注意其中左边的方式行不通,因为没有考虑背包的容量问题。
题目解析
最大子数组和
1.题目描述
2.解析思路及代码
确定状态:OPT(i)表示以i结尾的连续子数组的最大和。
OPT(0) = nums[0]
OPT(i) = max(OPT(i - 1) + nums[i], nums[i])
public int maxSubArray(int[] nums) {
if (nums.length == 0) return 0;
int[] res = new int[nums.length];
res[0] = nums[0];
int ans = nums[0];
for (int i = 1; i < nums.length; i ++ ) {
res[i] = Math.max(res[i - 1] + nums[i], nums[i]);
ans = Math.max(ans, res[i]);
}
return ans;
}
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
res = []
res.append(nums[0])
for i in nums[1:]:
res.append(max(res[-1] + i, i))
return max(res)
最长公共子序列
1.题目描述
2.解题思路及代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EIUsBlWO-1646490127700)(images/1007最长公共子序列状态转移方程.png)]
public int longestCommonSubsequence(String text1, String text2) {
int m =