1.编辑距离
import java.util.Scanner;
public class dp02 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String aStr = scan.nextLine();
String bStr = scan.nextLine();
int aLen = aStr.length();
int bLen = bStr.length();
int[][] dp = new int[aLen+1][bLen+1];
for(int i=0;i<aLen+1;i++){
dp[i][0] = i;
}
for(int i=0;i<bLen+1;i++){
dp[0][i] = i;
}
/**
* 允许的操作有增、删、替换
* dp[i][j]表示源串A位置i到目标串B位置j处最低需要操作的次数
* 如果末尾字符相等,那么:
* op[i][j]=op[i-1][j-1]
* 如果不相等:
* min{op[i-1][j]+1, op[i][j-1]+1, op[i-1][j-1]+1}
*/
for(int i=1;i<aLen+1;i++){
for(int j=1;j<bLen+1;j++){
if(aStr.charAt(i-1) == bStr.charAt(j-1)){//末位字符相等则不需要操作
dp[i][j] = dp[i-1][j-1];
}else {//
dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;//三种操作只需要一步
}
}
}
System.out.println(dp[aLen][bLen]);
}
}
2. 最大连续子序列
/**
* 求最大连续子序列和
* dp[n]表示以第n个数结尾的最大连续子序列的和,这里第n个数必须在子序列中
* dp[n] = max(0, dp[n-1]) + num[n]这么理解更合适
* 问题的答案是max(dp[m])
*/
//dp[i] = max{dp[i-1]+num[i],num[i]}
public class zixulie {
public static int maxSubArray(int[] nums) {
//int[] dp = new int[nums.length];
if(nums.length==1){
return nums[0];
}
int max = nums[0];
for (int i = 1; i < nums.length; i++) {
nums[i]=Math.max(nums[i],nums[i]+nums[i-1]);
if(max<nums[i]){
max = nums[i];
}
}
return max;
}
public static void main(String[] args){
int[] test = {-2,-1,2,4,-2};
int res = maxSubArray(test);
System.out.println(res);
for (int i: test
) {
System.out.println(i);
}
}
}
3.最长公共子串,返回长度以及子串
public class CommonStr {
public static void main(String[] args) {
String str1 = "acbcbcef";
String str2 = "abcbced";
System.out.println(getCommonStrLength(str1, str2));
}
/**
* 求两个字符串的最长公共子串
* @param str1
* @param str2
* @return
*/
private static int getCommonStrLength(String str1, String str2) {
int len1 = str1.length();
int len2 = str2.length();
int[][] dp = new int[len1 + 1][len2 + 1];
for (int i = 0; i <= len1; i++) {
for (int j = 0; j <= len2; j++) {
dp[i][j] = 0;
}
}
int maxLen = 0, maxEnd = 0;
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = 0;
}
if(dp[i][j]> maxLen){
maxLen = dp[i][j];
maxEnd = i-1;
}
}
}
System.out.println(str1.substring(maxEnd-maxLen+1,maxEnd+1));//endIndex -- 结束索引(不包括)。
return maxLen;
}
}
4.01背包问题,返回选的商品(二维)或者不返回(一维)。
public class dp {
public static void main(String[] args) {
new Solution1().canPartition(new int[]{0, 5, 5});
new Solution1().maxValue(new int[]{2,3,4,5},new int[]{3,4,5,6},10);
new Solution1().maxValue1(new int[]{2,3,4,5},new int[]{3,4,5,6},10);
}
}
class Solution1 {
public boolean canPartition(int[] nums) {
//背包问题,注意每个里面相当于存的不是价值。而是是否能恰好装满True or false
//dp[i][j] 表示前i个数能不能凑齐j ,注意j的含义是真正的容量,所以应该多添加一列
/*
dp[i][j] = dp[i-1][j] || (j-nums[i]>0 ? dp[i-1][j-nums[i]]:false) 要在这判断。
*/
int sum = 0;
for (int i : nums){
sum += i;
}
if((sum & 1) == 1){//奇数肯定不行
return false;
}
int n = nums.length;
int m = sum/2+1;
boolean[][] dp = new boolean[n][m];
for (int i=0; i<n;i++){
for (int j=0; j<m;j++){
if(i == 0){//如果为0,初始化第一个数,注意,为0的意思是第一个数
dp[i][j] = (nums[i] == j);
} else{
dp[i][j] = dp[i-1][j] || (j-nums[i]>=0? dp[i-1][j-nums[i]]:false);
}
}
}
return dp[n-1][m-1];
}
public int maxValue(int[] weight, int[] value, int max) {
/*
dp[i][j]在这里表示前i个样本j容量的背包最大能装多少价值的东西
https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html
*/
int n = weight.length+1;
int m = max + 1;
int [][] dp = new int[n][m];
for(int i=0;i<weight.length+1;i++){
dp[i][0] = 0;
}
for(int i=0;i<max+1;i++){
dp[0][i] = 0;
}
for (int i=1; i<=weight.length;i++){
for (int j=1; j<=max;j++){
if(weight[i-1]>j){
dp[i][j] = dp[i-1][j];
} else{
dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-weight[i-1]]+value[i-1]);
}
}
}
int i = n-1;
System.out.println(dp[n-1][m-1]);
while ( i>0){
if(dp[i][max] == dp[i-1][max]){
i=i-1;
} else {//if((max-weight[i-1])>=0 && (dp[i-1][max-weight[i-1]]+value[i-1] == dp[i][max]))要么就是上一个这个没加进去,要么就是这个加进去了
System.out.println("第"+i+"件商品价格"+value[i-1]);
max = max-weight[i-1];
i=i-1;
}
}
return dp[n-1][m-1];
}
public int maxValue1(int[] weight, int[] value, int max) {
/*
一维数组情况
dp[j]在这里表示j容量的背包最大能装多少价值的东西
倒着的原因是考虑前一背包
https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html
*/
int n = weight.length+1;
int m = max + 1;
int []dp = new int[m];
for (int i=1; i<=weight.length;i++){
for (int j=max; j>=weight[i-1];j--){//这里是逆序,但是如果是完全背包,则只需要在这改成正序即可
dp[j] = Math.max(dp[j],dp[j-weight[i-1]]+value[i-1]);//注意,应该是小于等于
}
}
System.out.println(dp[m-1]);
return dp[m-1];
}
}
)。