LeetCode712、两个字符串的最小ASCII删除和

题目描述

https://leetcode-cn.com/problems/minimum-ascii-delete-sum-for-two-strings/
在这里插入图片描述

解法

自顶向下的动态规划
看了这道题,其实很像寻找两个字符串的最长公共子序,因为这里要找最小ASCII码删除和,就像寻找最长公共子序一样,因为多出来的字符,它们肯定要删除的,而如果不是最长公共子序,必然删除得到的AscII码值之和必然更大。

所以题目可以使用两个字符串的最长公共子序的类似解法来做:

class Solution {
    
    
    int[][]memo;
    public int minimumDeleteSum(String s1, String s2) {
    
    
            //有想法一定要先执行,就像寻找最长公共子序一样因为多出来的字符,它们肯定要删除的
            //而不是最长公共子序,必然删除得到的AscII码值之和必然更大
        int m = s1.length(), n = s2.length();
        // 备忘录值为 -1 代表未曾计算
        memo = new int[m][n];
        for (int[] row : memo) 
            Arrays.fill(row, -1);
        return dp(s1,0,s2,0);
             
    }
    // 递归函数,自顶向下的递推,其问题的定义:计算 s1[i..] 和 s2[j..] 的最少步数
    int dp(String s1, int i, String s2, int j) {
    
    
        if (i == s1.length() ){
    
    
            int res=0;
            for(int k=j;k<s2.length();k++){
    
    
                res += s2.charAt(k);
            }
            return res;//全部删除
        }
        if(j == s2.length()) {
    
    
            int res = 0;
            for(int k=i;k<s1.length();k++){
    
    
                res += s1.charAt(k);
            }
            return res;//全部删除,此时s2为“”,则需要把s1全删除
        }
        // 如果之前计算过,则直接返回备忘录中的答案
        if (memo[i][j] != -1) {
    
    
            return memo[i][j];
        }
        // 根据 s1[i] 和 s2[j] 的情况做选择
        if (s1.charAt(i) == s2.charAt(j)) {
    
    
            memo[i][j] = dp(s1, i + 1, s2, j + 1);
        } else {
    
    
            memo[i][j] = Math.min(
                dp(s1, i + 1, s2, j)+s1.charAt(i),//只需删除1个
                dp(s1, i, s2, j + 1)+s2.charAt(j)//只需删除1个
                //两个都删除的情况被包含在上面
            );
        }
        return memo[i][j];
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_44861675/article/details/114486776
今日推荐