动态规划(Dynamic Programming)

动态规划的常规步骤

相关概念

无后效性

有后效性

练习-找零钱


此题在leetcode动态规划的方法讲解:



提交的代码:
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount+1];
Arrays.fill(dp, amount+1);
dp[0] = 0;
for(int i=1; i<=amount; i++){
for(int j=0; j<coins.length; j++){
if(coins[j]<=i){
dp[i] = Math.min(dp[i], dp[i-coins[j]]+1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
}
做这题时发现leetcode上的Integer.MAX_VALUE是个负数
练习-最长递增子序列

class Solution {
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
Arrays.fill(dp, 1);
dp[0] = 1;
int ans = 1;
for(int i=1; i<nums.length; i++){
for(int j=0; j<i; j++){
if(nums[i] > nums[j]){
dp[i] = Math.max(dp[i], dp[j]+1);
}
}
ans = Math.max(ans, dp[i]);
}
return ans;
}
}
这道题目的核心就是dp[i]存的是以nums[i]为结尾的最长递增子序列。
练习-最长公共子序列(二维动态规划)
先看看leetcode上的讲解


提交的代码
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int[][] dp = new int[text1.length()+1][text2.length()+1];
for(int i=1; i<=text1.length(); i++){
for(int j=1; j<=text2.length(); j++){
char c1 = text1.charAt(i-1);
char c2 = text2.charAt(j-1);
if(c1 == c2){
dp[i][j] = dp[i-1][j-1] + 1;
}
else{
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[text1.length()][text2.length()];
}
}
这道题经典二维动态规划的题目值得一背,最长公共子串同样可以用二维动态规划求解。
练习-0-1背包问题

leetcode上找不到题目,所以记住思路即可,0-1背包问题也是很经典的二维动态规划问题。
串(Sequence)
前缀、真前缀、后缀、真后缀

串匹配算法

蛮力法



KMP

蛮力与KMP对比

KMP-next表的使用


KMP-核心原理

KMP-真前缀后缀的最大公共子串长度

KMP-得到next


KMP-得到next数组的代码设计
虽然不是java代码,但相信也是看得懂的

有了next数组,相信后面文本串和模式串匹配的主代码完全不是问题了
KMP-不足之处

KMP-优化思路

说白了就是,不断根据next表向前找,找到一个与当前pi指向元素不一样的元素为止,避免根据next数组得到一个与原本相同的元素,进行不必要的比较
KMP-性能分析

略显尴尬的是,暴力法其实也就O(nm)左右的时间复杂度,暴力法耗时也不长。
文章介绍了动态规划的常规步骤,包括无后效性和有后效性的概念,并展示了找零钱、最长递增子序列和最长公共子序列的动态规划解决方案。此外,还探讨了KMP字符串匹配算法,包括其核心原理、next数组的构建以及时间复杂度分析。

被折叠的 条评论
为什么被折叠?



