这个也是通过看视频来总结的两个类型的问题关于动态规划问题

1.动态规划之选数问题

题目要求:

假设给定一串数字{1, 2, 4, 1, 7, 8, 3},我们要从中选择若干个数,使最后的和达到最大。选择的规则是,不能选相邻的数字。比如:如果我们选了第一个数字1,那么我们就不能选2,如果我们选择了数字4,那么我们就不能选择与它相邻的2和1。

动态规划的思想:将整个问题划分成一个个子问题,也就是说要求整个数列的最大和,可以先求出前面若干个数的和,一直划分到求出只有一个数的最大和(即本身),而每个子问题的解对于后面的结果都是有用的,这就是用到了动态规划的思想

思路:

对于每个数,都有选和不选两种状态,如果选了这个数,那么就不能选他相邻的那个数,那么最大和就等于本身加上他相邻的那位数之前那些数的最大和,如果不选这个数,那么便可以选它相邻的那个数,那么最大和就等于这个数之前的那些数的最大和。最终的结果就是取这两种选择的最大值

这里就可以使用递归,即Math.max(dp(arr, x-2)+arr[x], dp(arr, x-1));

递归的出口:

如果只有一个数,那么最大和就是本身
如果只有两个数,那么最大和就是这两个数中的最大值

1
2
3
4
5
6
7
8
9
public static int dp(int[] arr){
int[] temp=new int[arr.length];
temp[0]=arr[0];
temp[1]=Math.max(arr[0], arr[1]);
for(int i=2;i<arr.length;i++){
temp[i]=Math.max(temp[i-2]+arr[i],temp[i-1]);
}
return temp[arr.length-1];
}

2. 动态规划之最长公共子序列

题目描述:

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的公共子序列是这两个字符串所共同拥有的子序列。

若这两个字符串没有公共子序列,则返回 0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static int longestCommonSubsequence(String text1, String text2) {
int len1=text1.length();
int len2=text2.length();
char[] ch1=text1.toCharArray();
char[] ch2=text2.toCharArray();

//动态规划算法创建的二维数组一般都得多增一行一列,这是为了防止数组越界异常
int[][] p=new int[len1+1][len2+1];

//填表,第一行和第一列都为0,所以填表从下标为1的行和下标为1的列开始填
for(int i=1;i<p.length;i++){
for(int j=1;j<p[0].length;j++){
if(ch1[i-1]==ch2[j-1]){
p[i][j]=p[i-1][j-1]+1;
}else{
p[i][j]=Math.max(p[i-1][j], p[i][j-1]);
}
}
}
return p[len1][len2];
}
文章作者: Mr. Fortunate
文章链接: https://www.fortunate.cool/2022/08/13/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 fortunate

评论