zoukankan      html  css  js  c++  java
  • 最长公共子序列算法问题代码(使用JavaScript实现)

    问题描述

    问题描述

    题目描述:求得两个数组的最长公共子序列.子序列不要求是连续的.但是要求是有的(增序).

    比如字符串1:['B','D','C','A','B','A'];字符串2:['A','B','C','B','D''A','B'].

    则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA

    • 这是一个动态规划的题目。对于可用动态规划求解的问题,一般有两个特征:
      • 最优子结构;
      • 重叠子问题:

    问题推理

    具体分析 : 王陸.

    问题抽象

    • 设c[i,j]为:x[1,i],y[1,j]的最长公共子序列长度.
      • 如果 x[i] == y[j].那么c[i][j] == (x[1,i-1],y[1,j-1]) +1
      • 如果 x[i] != y[j].那么 c[i][j] == max( (x[1,i-1],y[1,j]) || (x[1,i],y[1,j-1]) )
    • 回溯表的记录是如果left/top/left_top表示当前元素的最优质是使用的之前的哪一个子元素.
      个人感觉动态规划就是把主问题的所有子问题穷尽求出最优解.把这些解放到一张里.个人感觉动态规划一般用于求最值的情况下.

    我们思考的时候是要从最底层的问题层层递进的思考.从最简单的事情开始推理.

    图示


    代码实现:动态规划

    代码实现

     let list_a = ['A', 'B', 'C', 'B', 'D', 'A', 'B']; //序列一
            let list_b = ['B', 'D', 'C', 'A', 'B', 'A'];//序列二
    
    
            let table_dp = []; // 记录各种情况的动态表
            for (var i = 0; i <= list_a.length; i++) { // i是y轴
                table_dp[i] = [];
                for (var j = 0; j <= list_b.length; j++) { // j是x轴
                    table_dp[i][j] = 0;
                }
            }
            // table_dp 二维空数组生成完毕.
    
            let table_rec = new Array();//回溯表
            for (let i = 0; i < list_a.length; i++) {
                table_rec[i] = [];
                for (let j = 0; j < list_b.length; j++) {
                    table_rec[i][j] = null;
                }
            }
            // table_rec 二维空数组生成完毕.
    
    
    
            // 动态规划代码开始
            for (let i = 1; i <= list_a.length; i++) { // x==0 || y==0 的情况下,均为0.所以从1开始.设置从1开始也是为了好查表.
    
                for (j = 1; j <= list_b.length; j++) {
    
                    if (list_a[i - 1] === list_b[j - 1]) { // 两个数组是要从下表为0开始遍历数据的
                        table_dp[i][j] = table_dp[i - 1][j - 1] + 1;
                        table_rec[i - 1][j - 1] = 'left_top';
                    } else {
    
                        let max_num;
                        if (table_dp[i - 1][j] > table_dp[i][j - 1]) {
                            max_num = table_dp[i - 1][j];
                            table_rec[i - 1][j - 1] = 'top';
                        }else {
                            max_num = table_dp[i][j - 1];
                            table_rec[i - 1][j - 1] = 'left';
                        }
    
                        table_dp[i][j] = max_num;
                    }
                }
            }
            // 动态规划代码结束
    

    循环回溯

    
            // 使用while回溯
            let result = [];// 记录结果(倒序).
            x_axis_length = table_rec[0].length - 1;//二维数组x轴.
            y_axis_length = table_rec.length - 1;//二维数组y轴
    
            while (x_axis_length >= 0 && y_axis_length >= 0) {
                if (table_rec[y_axis_length][x_axis_length] == 'left_top') {
                    result.push(list_a[y_axis_length])
                    x_axis_length -= 1;
                    y_axis_length -= 1;
                } else if (table_rec[y_axis_length][x_axis_length] == 'top') {
                    y_axis_length -= 1;
                } else {
                    x_axis_length -= 1;
                }
    
            }
            // 使用while结束
    
    
    

    递归回溯

    
            // 使用递归回溯
            let x_axis_length_ = table_rec[0].length - 1;//二维数组x轴
            let y_axis_length_ = table_rec.length - 1;//二维数组y轴
            const result_recursion = [] // 记录结果(倒序).
    
            function recursion_rec(rec_list, dp_list, x_axis, y_axis) {
    
                if (x_axis < 0 || y_axis < 0) {
                    return 0;
                }
                if (rec_list[y_axis][x_axis] == 'left_top') {
                    result_recursion.push(list_a[y_axis]);
                    recursion_rec(rec_list, dp_list, x_axis - 1, y_axis - 1);
                } else if (rec_list[y_axis][x_axis] == 'left') {
                    recursion_rec(rec_list, dp_list, x_axis - 1, y_axis);
                } else {
                    recursion_rec(rec_list, dp_list, x_axis, y_axis - 1);
                }
    
            }
            // 使用递归结束
    
            recursion_rec(table_rec, table_dp, x_axis_length_, y_axis_length_)
    
    
            // 打印结果      
            console.log(table_dp, table_rec)
            console.log(result);
            console.log(result_recursion)
      
    




    参考

  • 相关阅读:
    pg 基础操作
    mybatis+pg常见错误
    mybatis 需要注意事项
    java编程中的Dao,service,controller,View
    java 中的spring基础
    werkzeug(flask)中的local,localstack,localproxy探究
    gevent
    cookie和session
    关于redis数据库的简单思考
    对阻塞,非阻塞,同步,异步的深入理解
  • 原文地址:https://www.cnblogs.com/gtscool/p/12576553.html
Copyright © 2011-2022 走看看