• 算法体系-21 第二十一 暴力递归到动态规划(三)


    一 最长回文子串

    1.1 描述

    给定一个字符串str,返回这个字符串的最长回文子序列长度

    比如 : str = “a12b3c43def2ghi1kpm”

    最长回文子序列是“1234321”或者“123c321”,返回长度7

    1.2 分析

    1.2.1 先将原传逆序,求原串和反转后的串的最长公共子序列就是原串的最长回文子序列

    1.2 分析

    1.2.1 先将原传逆序,求原串和反转后的串的最长公共子序列就是原串的最长回文子序列

    1.3 反转求最长公共子序列 代码

    1. public static int longestPalindromeSubseq1(String s) {
    2. if (s == null || s.length() == 0) {
    3. return 0;
    4. }
    5. if (s.length() == 1) {
    6. return 1;
    7. }
    8. char[] str = s.toCharArray();
    9. char[] reverse = reverse(str);
    10. return longestCommonSubsequence(str, reverse);
    11. }
    12. public static int longestCommonSubsequence(char[] str1, char[] str2) {
    13. int N = str1.length;
    14. int M = str2.length;
    15. int[][] dp = new int[N][M];
    16. dp[0][0] = str1[0] == str2[0] ? 1 : 0;
    17. for (int i = 1; i < N; i++) {
    18. dp[i][0] = str1[i] == str2[0] ? 1 : dp[i - 1][0];
    19. }
    20. for (int j = 1; j < M; j++) {
    21. dp[0][j] = str1[0] == str2[j] ? 1 : dp[0][j - 1];
    22. }
    23. for (int i = 1; i < N; i++) {
    24. for (int j = 1; j < M; j++) {
    25. dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
    26. if (str1[i] == str2[j]) {
    27. dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - 1] + 1);
    28. }
    29. }
    30. }
    31. return dp[N - 1][M - 1];
    32. }

    1.3.1 分析二 上节用的是样本对应模型,这里用别的做法 (范围尝试模型 这种模型特别在乎讨论开头如何如何 结尾如何如何)

    样本对应模型(特别在乎两个样本结尾如何如何) 范围尝试模型往开头如何如何,结尾如何如何

    范围讨论如下-递归含义的定义如下

    1.3.2 分析 有以下四种情况

    1)不以L开头,不以R结尾

    2)以L开头,不以R结尾

    3)不以L开头,以R结尾

    4)以L开头,以R结尾

    1.4 尝试递归代码

    1. public static int lpsl1(String s) {
    2. if (s == null || s.length() == 0) {
    3. return 0;
    4. }
    5. char[] str = s.toCharArray();
    6. return f(str, 0, str.length - 1);
    7. }
    8. // str[L..R]最长回文子序列长度返回
    9. public static int f(char[] str, int L, int R) {
    10. if (L == R) {
    11. return 1;
    12. }
    13. if (L == R - 1) {
    14. return str[L] == str[R] ? 2 : 1;
    15. }
    16. int p1 = f(str, L + 1, R - 1);
    17. int p2 = f(str, L, R - 1);
    18. int p3 = f(str, L + 1, R);
    19. int p4 = str[L] != str[R] ? 0 : (2 + f(str, L + 1, R - 1));
    20. return Math.max(Math.max(p1, p2), Math.max(p3, p4));
    21. }

    1.5 改动态规划分析

    除了if (L == R) {

    return 1;}

    if (L == R - 1) {

    return str[L] == str[R] ? 2 : 1;}

    这两位置之后,其他位置的填的方法 从底往上填 每一行从左往右er

    //跟进下面得图形推导出所求剩下得范围

    for (int i = N - 3; i >= 0; i--)

    for (int j = i + 2; j < N; j++)

    1.6改动太规划代码

    1. public static int longestPalindromeSubseq2(String s) {
    2. if (s == null || s.length() == 0) {
    3. return 0;
    4. }
    5. if (s.length() == 1) {
    6. return 1;
    7. }
    8. char[] str = s.toCharArray();
    9. int N = str.length;
    10. int[][] dp = new int[N][N];
    11. dp[N - 1][N - 1] = 1;
    12. for (int i = 0; i < N - 1; i++) {
    13. dp[i][i] = 1;
    14. dp[i][i + 1] = str[i] == str[i + 1] ? 2 : 1;
    15. }
    16. //跟进上面得图形推导出所求剩下得范围
    17. for (int i = N - 3; i >= 0; i--) {
    18. for (int j = i + 2; j < N; j++) {
    19. dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]);
    20. if (str[i] == str[j]) {
    21. dp[i][j] = Math.max(dp[i][j], dp[i + 1][j - 1] + 2);
    22. }
    23. }
    24. }
    25. return dp[0][N - 1];
    26. }
    27. }

    二 返回象棋从一个位置到另一个位置的方法有多少种

    2.1 描述

    请同学们自行搜索或者想象一个象棋的棋盘,

    然后把整个棋盘放入第一象限,棋盘的最左下角是(0,0)位置

    那么整个棋盘就是横坐标上9条线、纵坐标上10条线的区域

    给你三个 参数 x,y,k

    返回“马”从(0,0)位置出发,必须走k步

    最后落在(x,y)上的方法数有多少种?

    象棋走的日

    2.2 分析 样本对应模型

    跳的所有8方法

    2.3 递归代码

    1. // 当前来到的位置是(x,y)
    2. // 还剩下rest步需要跳
    3. // 跳完rest步,正好跳到a,b的方法数是多少?
    4. // 10 * 9
    5. public static int jump(int a, int b, int k) {
    6. return process(0, 0, k, a, b);
    7. }
    8. public static int process(int x, int y, int rest, int a, int b) {
    9. if (x < 0 || x > 9 || y < 0 || y > 8) {
    10. return 0;
    11. }
    12. if (rest == 0) {
    13. return (x == a && y == b) ? 1 : 0;
    14. }
    15. int ways = process(x + 2, y + 1, rest - 1, a, b);
    16. ways += process(x + 1, y + 2, rest - 1, a, b);
    17. ways += process(x - 1, y + 2, rest - 1, a, b);
    18. ways += process(x - 2, y + 1, rest - 1, a, b);
    19. ways += process(x - 2, y - 1, rest - 1, a, b);
    20. ways += process(x - 1, y - 2, rest - 1, a, b);
    21. ways += process(x + 1, y - 2, rest - 1, a, b);
    22. ways += process(x + 2, y - 1, rest - 1, a, b);
    23. return ways;
    24. }

    2.4 改动态规划

    是个三维数组,要的是rest的数据,rest要的数据是rest-1的数据 最终rest==0又是知道的

    1. public static int dp(int a, int b, int k) {
    2. int[][][] dp = new int[10][9][k + 1];
    3. dp[a][b][0] = 1;
    4. for (int rest = 1; rest <= k; rest++) {
    5. for (int x = 0; x < 10; x++) {
    6. for (int y = 0; y < 9; y++) {
    7. int ways = pick(dp, x + 2, y + 1, rest - 1);
    8. ways += pick(dp, x + 1, y + 2, rest - 1);
    9. ways += pick(dp, x - 1, y + 2, rest - 1);
    10. ways += pick(dp, x - 2, y + 1, rest - 1);
    11. ways += pick(dp, x - 2, y - 1, rest - 1);
    12. ways += pick(dp, x - 1, y - 2, rest - 1);
    13. ways += pick(dp, x + 1, y - 2, rest - 1);
    14. ways += pick(dp, x + 2, y - 1, rest - 1);
    15. dp[x][y][rest] = ways;
    16. }
    17. }
    18. }
    19. return dp[0][0][k];
    20. }
    21. public static int pick(int[][][] dp, int x, int y, int rest) {
    22. if (x < 0 || x > 9 || y < 0 || y > 8) {
    23. return 0;
    24. }
    25. return dp[x][y][rest];
    26. }

  • 相关阅读:
    SSM学习——Spring事务(9)
    SpringCloud Alibaba-Sentinel保姆级教程
    手游帧率不稳定的原因是什么?
    智能车竞赛新手入门电磁(0基础)(通俗易懂)
    C++ Reference: Standard C++ Library reference: C Library: cwchar: putwchar
    计算机毕业设计Java大型商场应急预案管理系统(源码+系统+mysql数据库+lw文档)
    LabVIEW编程开发NI-USRP
    2023最新SSM计算机毕业设计选题大全(附源码+LW)之java家具商城hog7l
    web前端三大主流框架
    微服务系统设计——API 网关服务设计
  • 原文地址:https://blog.csdn.net/m0_61164038/article/details/139655747