算法导论:最长公共子序列问题(动态规划+贪心+二分查找)


import com.sun.org.apache.regexp.internal.RE;

import java.sql.PreparedStatement;

public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        char[] A = "ABCBDAB".toCharArray();
        char[] B = "BDCABA".toCharArray();
        main.LCS_LENGTH(A,B);
        System.out.println();

        int[] NUM = {10,9,2,5,3,7,101,18};
        main.MONOTONE_INCREASING(NUM);
        main.MONOTONE_INCREASING_OPTIMAL(NUM);
    }
    //自底向上
    public void LCS_LENGTH(char[] X, char[] Y) {
        int m = X.length;
        int n = Y.length;
        char[][] b = new char[m + 1][n + 1];
        int[][] c = new int[m + 1][n + 1];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (X[i]==Y[j]){
                    c[i + 1][j + 1] = c[i][j] + 1;
                    b[i+1][j+1]='↖';
                } else if (c[i][j + 1] < c[i + 1][j]) {
                    c[i + 1][j + 1] = c[i + 1][j];
                    b[i + 1][j + 1] = '←';
                }else {
                    c[i + 1][j + 1] = c[i][j + 1];
                    b[i + 1][j + 1] = '↑';
                }
                System.out.print(b[i + 1][j + 1]);
            }
            System.out.println();
        }
        System.out.println("最长公共子序列长度为:"+c[m][n]);
        System.out.print("最长公共子序列为:");
        PRINT_LCS(b,X,m,n);
    }
    //带备忘录
    public int LCS_LENGTH_MEMORIZED(char[] X, char[] Y,int c[][],char b[][],int i,int j) {
        if (i == 0 || j == 0) {
            PRINT_LCS(b, X, X.length + 1, Y.length + 1);
        }
        if (X[i] == Y[j]) {
            return c[i + 1][j + 1] = LCS_LENGTH_MEMORIZED(X, Y, c, b, i-1, j-1);
        }else return  c[i + 1][j + 1] = Math.max(LCS_LENGTH_MEMORIZED(X, Y, c, b, i-1, j),LCS_LENGTH_MEMORIZED(X, Y, c, b, i, j-1));
    }
    //打印结果
    public void PRINT_LCS(char[][] b, char[] X, int i, int j) {
        if (i==0||j==0) return;
//        if(X[i]==X[j]){ 15.4-2习题
        if (b[i][j]=='↖'){
            PRINT_LCS(b, X, i - 1, j - 1);
            System.out.print(X[i-1]);
        } else if (b[i][j] == '↑') {
            PRINT_LCS(b,X,i-1,j);
        }else PRINT_LCS(b,X,i,j-1);
    }

    //练习14.4-5 O(n2)的单调递增子序列
    public void MONOTONE_INCREASING(int[] NUM) {
        if (NUM.length==0) return;
        int RES=1;
        int c[] = new int[NUM.length];
        for (int i=0;i<c.length; i++) { c[i]=1; }
        for (int i = 1; i < NUM.length; i++) {
            int curr=1;
            for (int j = i - 1; j >= 0; j--) {
                if (NUM[j] < NUM[i]) {
                    curr = curr > 1 + c[j] ? curr : 1 + c[j];
                }
            }
            c[i] = curr;
            RES = RES > c[i] ? RES : curr;
        }
        System.out.println(RES);
    }
    //练习14.4-6 O(nlgn)最长单调子序列int[] NUM = {5, 6, 1, 3, 4, 9, 1, 6, 5, 6};
    public void MONOTONE_INCREASING_OPTIMAL(int[] NUM) {
        int len = 1, n = NUM.length;
        if (n == 0) return ;
        int[] d = new int[n + 1];
        for (int i = 1; i < n; ++i) {
            if (NUM[i] > d[len]) d[++len] = NUM[i];
            else{
                int l = 1, r = len, pos = 0; // 如果找不到说明所有的数都比 nums[i] 大,此时要更新 d[1],所以这里将 pos 设为 0
                while (l <= r) {
                    int mid = (l + r) >> 1;
                    if (d[mid] < NUM[i]) {
                        pos = mid;
                        l = mid + 1;
                    }
                    else r = mid - 1;
                }
                d[pos + 1] = NUM[i];
            }
        }
        System.out.println(len);
        return ;
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值