动态规划(三)背包问题、回文串分割(Palindrome Partitioning)、编辑距离(Edit Distance)、不同子序列(Distinct Subsequences)

背包问题

https://www.lintcode.com/problem/backpack-ii/description

  • 问题描述与解决思路
    在这里插入图片描述
  • 代码
public class Solution {
    
    
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @param V: Given n items with value V[i]
     * @return: The maximum value
     */
    public int backPackII(int m, int[] A, int[] V) {
    
    
        // write your code here
        /*
        if (m == 0) return 0;
        if (A == null || V == null) return 0;
        if (A.length == 0 || V.length == 0) return 0;
        
        //构建二维数组存放最大值
        int[][] answers = new int[A.length + 1][m + 1];
        
        //java在初始化数组的时候已经默认全填充为0
        //所以直接按第二行第二列开始运算即可
        //行表示放的第几个物品
        //列表示此时包的大小
        for (int row = 1; row < answers.length; row++) {
            for (int col = 1; col < m + 1; col ++) {
                if (col >= A[row - 1]) {
                    //放的下
                    answers[row][col] = Math.max(V[row - 1] + answers[row - 1][col - A[row - 1]], answers[row - 1][col]);
                } else {
                    //表示放不下
                    answers[row][col] = answers[row - 1][col];
                }
            }
        }
        //返回最后一个数据
        return answers[A.length][m];
        */
        //方法二优化内存
        if (m == 0) return 0;
        if (A == null || V == null) return 0;
        if (A.length == 0 || V.length == 0) return 0;
        //只用一维数组表示上一行的情况就行
        //这个数组的长度就是包的最大值加一
        int[] answers = new int[m + 1];
        //还是从第一个物品开始计算
        for (int row = 1; row < A.length + 1; row++) {
    
    
            //在判断放下放不下的时候因为我们保保存的是一行数据
            //所以要从后往前遍历
            for (int col = m; col >= 1; col--) {
    
    
                if (col >= A[row - 1]) {
    
    
                    //表示放的下
                    answers[col] = Math.max(V[row - 1] + answers[col - A[row - 1]], answers[col]);
                }
            }
        }
        return answers[m];
        
    }
}

回文串分割(Palindrome Partitioning)

  • 问题描述与解决思路
    在这里插入图片描述
  • 代码
//回文串分割(Palindrome Partitioning)
    public int minCut(String s) {
    
    

        if (s == null) return 0;
        if (s.length() == 0) return 0;

        //设置一个一维数组保存f[i]
        int[] f = new int[s.length() + 1];
        for (int i = 0; i < f.length; i++) {
    
    
            //初始化f[i]等于当前字符串最大分割次数
            f[i] = i - 1;
        }
        //index表示index下标前的字符串
        for (int index = 1; index <= s.length(); index++) {
    
    
            //i表示模拟分割的地方 为了方便看整体 i应该模拟分割从0开始
            for (int i = 0; i < index; i++) {
    
    
                if (isHuiWen(s, i, index - 1)) {
    
    
                    f[index] = Math.min(f[index], f[i] + 1);
                }
            }
        }
        return f[s.length()];
    }

    private boolean isHuiWen(String s, int start, int end) {
    
    

        while (start < end) {
    
    
            if (s.charAt(start) != s.charAt(end)) {
    
    
                return false;
            }
            start++;
            end--;
        }
        return true;
    }

编辑距离(Edit Distance)

  • 问题描述与解决思路
    在这里插入图片描述
  • 代码
//编辑距离(Edit Distance)
    public int minDistance(String word1, String word2) {
    
    
        
        if (word1 == null && word2 == null) return 0;
        if (word1 == null || word1.length() == 0) {
    
    
            return word2.length();
        }
        if (word2 == null || word2.length() == 0) {
    
    
            return word1.length();
        }
        
        int len1 = word1.length();
        int len2 = word2.length();
        //初始化一个二维数组
        int[][] answers = new int[len1 + 1][len2 + 1];
        //初始化第一列的数据
        for (int i = 0; i < len1 + 1; i++) {
    
    
            answers[i][0] = i;
        }
        //初始化第一行的数据
        for (int i = 0; i < len2 + 1; i++) {
    
    
            answers[0][i] = i;
        }
        //从第二行第二列开始看起
        for (int row = 1; row < len1 + 1; row++) {
    
    
            for (int col = 1; col < len2 + 1; col++) {
    
    
                answers[row][col] = Math.min(answers[row - 1][col], answers[row][col]) + 1;
                //判断字符是不是相同
                if (word1.charAt(row - 1) == word2.charAt(col - 1)) {
    
    
                    //当前字符相同
                    answers[row][col] = Math.min(answers[row][col], answers[row - 1][col - 1]);
                } else {
    
    
                    //当前字符不相等, 还需要在变换一次
                    answers[row][col] = Math.min(answers[row][col], answers[row - 1][col - 1] + 1);
                }
            }
        }
        return answers[len1][len2];
    }

不同子序列(Distinct Subsequences)

https://www.nowcoder.com/questionTerminal/ed2923e49d3d495f8321aa46ade9f873

  • 问题描述与解题思路
    在这里插入图片描述
  • 代码
public class Solution {
    
    

    /**
     * 不同子序列(Distinct Subsequences)
     * @param S
     * @param T
     * @return
     */
    public int numDistinct(String S, String T) {
    
    

        if (T == null && S == null) return 1;
        if (S == null || S.length() == 0) return 0;
        if (T == null || T.length() == 0) return 1;

        int len1 = S.length();
        int len2 = T.length();
        //构建二维数组
        int[][] answers = new int[len1 + 1][len2 + 1];
        //第一行表示S为空 所以是0
        //第一列表示T为空 所以是1
        for (int i = 0; i < len1 + 1; i++) {
    
    
            answers[i][0] = 1;
        }
        //从第二行第二列开始计算数目
        for (int row = 1; row < len1 + 1; row++) {
    
    
            for (int col = 1; col < len2 + 1; col++) {
    
    
                //判断当前字符是不是相等
                if (S.charAt(row - 1) == T.charAt(col - 1)) {
    
    
                    //表示相等
                    answers[row][col] = answers[row - 1][col - 1] + answers[row - 1][col];
                } else {
    
    
                    //表示不相等
                    answers[row][col] = answers[row - 1][col];
                }
            }
        }
        return answers[len1][len2];
    }

    //内存优化
    public int numDistinct2(String S, String T) {
    
    
        if (T == null && S == null) return 1;
        if (S == null || S.length() == 0) return 0;
        if (T == null || T.length() == 0) return 1;

        //构建一个一维数组长度是T的长度加一
        int[] answers = new int[T.length() + 1];
        //第一个数字设置为1其余为0
        answers[0] = 1;
        //从第二行第二列开始看起
        for (int row = 1; row < S.length()+ 1; row++) {
    
    
            //为了不影响前面数据计算 必须从后往前计算
            for (int col = T.length(); col > 0; col--) {
    
    
                //这里的操作还是判断当前字符是不是相等
                if (S.charAt(row - 1) == T.charAt(col - 1)) {
    
    
                    //当前字符相等
                    answers[col] += answers[col - 1];
                }
            }
        }
        return answers[T.length()];
    }
}

猜你喜欢

转载自blog.csdn.net/Shangxingya/article/details/108554038