1. 程式人生 > 其它 >712. 兩個字串的最小ASCII刪除和

712. 兩個字串的最小ASCII刪除和

技術標籤:動態規劃演算法動態規劃javaleetcode

連結串列演算法題(程式設計師面試寶典)

解題思路主要來源於leetcode官方與《程式設計師面試寶典》。

712. 兩個字串的最小ASCII刪除和

給定兩個字串s1, s2,找到使兩個字串相等所需刪除字元的ASCII值的最小和。

示例 1:

輸入: s1 = “sea”, s2 = “eat”
輸出: 231
解釋: 在 “sea” 中刪除 “s” 並將 “s” 的值(115)加入總和。
在 “eat” 中刪除 “t” 並將 116 加入總和。
結束時,兩個字串相等,115 + 116 = 231 就是符合條件的最小和。
示例 2:

輸入: s1 = “delete”, s2 = “leet”
輸出: 403
解釋: 在 “delete” 中刪除 “dee” 字串變成 “let”,
將 100[d]+101[e]+101[e] 加入總和。在 “leet” 中刪除 “e” 將 101[e] 加入總和。
結束時,兩個字串都等於 “let”,結果即為 100+101+101+101 = 403 。
如果改為將兩個字串轉換為 “lee” 或 “eet”,我們會得到 433 或 417 的結果,比答案更大。
注意:

0 < s1.length, s2.length <= 1000。
所有字串中的字元ASCII值在[97, 122]之間。

解題方法

參考資料1:https://mp.weixin.qq.com/s/ZhPEchewfc03xWv9VP3msg

解題思路1

class Solution {

    //備忘錄
    int[][] memo;
    public int minimumDeleteSum(String s1, String s2) {
        //帶備忘錄的遞迴法
        //與最長公共子序列演算法相似
        memo = new int[s1.length()][s2.length()];
        for(int[] row:memo){
            //-1 表示未進行操作
            Arrays.fill(row,-1);
        }

        return dp(s1,0,s2,0);
    }

    //定義:將 s1[i..] s2[j..] 刪除成相同的子序列,最小的 ASCII 碼之和為 dp(s1, i, s2, j)
    public int dp(String s1,int i,String s2,int j){

        //base case
        int res = 0;
        if(i==s1.length()){
            //如果一個字串為空,肯定要將另一個字串刪除完
            for(;j<s2.length();j++){
                res += s2.charAt(j);
            }
            return res;
        }
        if(j==s2.length()){
            //如果一個字串為空,肯定要將另一個字串刪除完
            for(;i<s1.length();i++){
                res += s1.charAt(i);
            }
            return res;
        }

        if(memo[i][j]!=-1){
            return memo[i][j];
        }

        if(s1.charAt(i)==s2.charAt(j)){
            //不進行刪除操作
            memo[i][j] = dp(s1,i+1,s2,j+1);
        }else{
            //s1[i] s2[j] 至少刪除一個
            memo[i][j] = Math.min(
                s1.charAt(i) + dp(s1,i+1,s2,j),
                s2.charAt(j) + dp(s1,i,s2,j+1)
            );
        }
        return memo[i][j];

    }
}

在這裡插入圖片描述

解題思路2

動態規劃,迭代

class Solution {


    public int minimumDeleteSum(String s1, String s2) {

        //動態規劃 迭代
        //dp[i][j] 代表s1[1..i]  s2[1..j] 刪除成相同子序列,最小的ASCII值
        int[][] dp = new int[s1.length()+1][s2.length()+1];
        //base case
        for(int[] row:dp){
            Arrays.fill(row,0);
        }
        int val = 0;
        for(int i=1;i<=s1.length();i++){
            val += s1.charAt(i-1);
            dp[i][0] = val;  
        }
        val = 0;
        for(int i=1;i<=s2.length();i++){
            val += s2.charAt(i-1);
            dp[0][i] = val;  
        }

        for(int i=1;i<=s1.length();i++){
            for(int j=1;j<=s2.length();j++){
                if(s1.charAt(i-1)==s2.charAt(j-1)){
                    //相同的字元不用進行刪除操作
                    dp[i][j] = dp[i-1][j-1];
                }else{
                    //不同的話,s1[i-1] s2[j-1] 兩個至少刪除一個字元
                    dp[i][j] = Math.min(s1.charAt(i-1)+dp[i-1][j],s2.charAt(j-1)+dp[i][j-1]);
                }
            }
        }

        return dp[s1.length()][s2.length()];

    }

    
}

在這裡插入圖片描述

解題思路3

class Solution {


    public int minimumDeleteSum(String s1, String s2) {
        //將最小ASCII刪除和  轉換為最大公共子序列的最大ASCII值和
        //動態規劃 迭代
        //dp[i][j] 代表s1[1..i]  s2[1..j] 中最大公共子序列的最大ACSII值
        int[][] dp = new int[s1.length()+1][s2.length()+1];
        //base case
        for(int[] row:dp){
            Arrays.fill(row,0);
        }

        for(int i=1;i<=s1.length();i++){
            for(int j=1;j<=s2.length();j++){
                if(s1.charAt(i-1)==s2.charAt(j-1)){
                    //相同的字元
                    dp[i][j] = dp[i-1][j-1]+s1.charAt(i-1);
                }else{
                    //不同的話,
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
        int sum = 0;
        for(int i=0;i<s1.length();i++){
            sum += s1.charAt(i);
        }
        for(int i=0;i<s2.length();i++){
            sum += s2.charAt(i);
        }

        //返回值:兩數的ASCII值和  減去 2* 最大公共子序列的最大ASCII值和
        return sum-2*dp[s1.length()][s2.length()];

    }
}

在這裡插入圖片描述