动态规划问题关键特征
/**
- @Author leijs
@date 2022/4/15 */ public class Fibnacci { public static void main(String[] args) {
long start = System.currentTimeMillis();System.out.println(fibnacci(40));long end = System.currentTimeMillis();System.out.println(end - start);long start1 = System.currentTimeMillis();System.out.println(fibnacci2(40));long end1 = System.currentTimeMillis();System.out.println(end1 - start1);
}
public static int fibnacci2(int n) {
int[] res = new int[n + 1];res[0] = 0;res[1] = 1;res[2] = 1;if (n > 2) {for (int i = 3; i <= n; i++) {res[i] = res[i - 1] + res[i - 2];}}return res[n];
}
// 递归实现 public static int fibnacci(int n) {
if (n == 1 || n == 2) {return 1;}return fibnacci(n - 1) + fibnacci(n - 2);
} }
<a name="bUEBf"></a>## 钢条切割问题<br /><br /><br />> 小问题的最优解可以转化为大问题的最优解```javapackage com.algorithm.demo.dongtaiguihua;import com.alibaba.fastjson.JSONObject;import com.google.common.collect.Lists;import java.util.List;/*** @Author leijs* @date 2022/4/15*/public class CutRod {public static int[] price = new int[]{0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30};public static void main(String[] args) {long start = System.nanoTime();System.out.println(cutRodRecurision(price, 9));long end = System.nanoTime();System.out.println(end - start);long start1 = System.nanoTime();System.out.println(cutRodRecurision2(price, 9));long end1 = System.nanoTime();System.out.println(end1 - start1);long start2 = System.nanoTime();System.out.println(cutRodDp(price, 9));long end2 = System.nanoTime();System.out.println(end2 - start2);long start3 = System.nanoTime();System.out.println(cutRodDpExtend(price, 9)[9]);long end3 = System.nanoTime();System.out.println(end3 - start3);}public static int cutRodRecurision2(int[] price, int n) {// 左边不切割,右边切割的场景if (0 == n) {// 长度是0return 0;}int res = price[n];for (int i = 1; i <= n; i++) {res = Math.max(res, price[i] + cutRodRecurision(price, n - i));}return res;}public static int cutRodRecurision(int[] price, int n) {if (0 == n) {// 长度是0return 0;}int res = price[n];for (int i = 1; i < n; i++) {res = Math.max(res, cutRodRecurision(price, i) + cutRodRecurision(price, n - i));}return res;}public static int cutRodDp(int[] price, int n) {int[] r = new int[n + 1];r[0] = 0;for (int i = 1; i <= n; i++) {int res = 0;for (int j = 1; j < i + 1; j++) {res = Math.max(res, price[j] + r[i - j]);}r[i] = res;}return r[n];}public static int[] cutRodDpExtend(int[] price, int n) {int[] r = new int[n + 1];// 左边这一段的值int[] s = new int[n + 1];r[0] = 0;s[0] = 0;for (int i = 1; i <= n; i++) {// res价格的最优值int res_r = 0;// 价格最大值对应方案左边不切割部分的长度int res_s = 0;for (int j = 1; j < i + 1; j++) {if (price[j] + r[i - j] > res_r) {res_r = price[j] + r[i - j];res_s = j;}}r[i] = res_r;s[i] = res_s;}System.out.println("res_s is :" + JSONObject.toJSONString(s));List<Integer> ans = Lists.newArrayList();while (n > 0) {ans.add(s[n]);n -= s[n];}System.out.println("ans is :" + JSONObject.toJSONString(ans));System.out.println("r is :" + JSONObject.toJSONString(r));return r;}}
最长公共子序列




package com.algorithm.demo.dongtaiguihua;/*** @Author leijs* @date 2022/4/16*/public class LcsLength {public static void main(String[] args) {System.out.println(lcsLength("ABCBDAB".toCharArray(), "BDCABA".toCharArray()));System.out.println(lcs("ABCBDAB".toCharArray(), "BDCABA".toCharArray()));}public static int lcs(char[] a, char[] b) {int m = a.length;int n = b.length;int[][] arr = new int[m + 1][n + 1];int[][] c = new int[m + 1][n + 1]; // 1 左上方 2 上方 3 左方for (int i = 1; i < m + 1; i++) {for (int j = 1; j < n + 1; j++) {// 这两个位置字符匹配时,来自左上角 +1if (a[i - 1] == b[j - 1]) {arr[i][j] = arr[i - 1][j - 1] + 1;c[i][j] = 1;} else if (arr[i - 1][j] > arr[i][j - 1]) {arr[i][j] = arr[i - 1][j];c[i][j] = 2;} else {arr[i][j] = arr[i][j - 1];c[i][j] = 3;}}}// trace backStringBuilder sb = new StringBuilder();int i = m;int j = n;while (i > 0 && j > 0) {if (c[i][j] == 1) {sb.append(a[i - 1]);i -= 1;j -= 1;} else if (c[i][j] == 2) {i -= 1;} else {j -= 1;}}System.out.println("res:" + sb);return arr[m][n];}public static int lcsLength(char[] a, char[] b) {int m = a.length;int n = b.length;int[][] arr = new int[m + 1][n + 1];for (int i = 1; i < m + 1; i++) {for (int j = 1; j < n + 1; j++) {// 这两个位置字符匹配时,来自左上角if (a[i - 1] == b[j - 1]) {arr[i][j] = arr[i - 1][j - 1] + 1;} else {arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);}}}return arr[m][n];}}

