【動的計画法アルゴリズム演習】day11


1. 1312. 文字列が回文になるための最小挿入数

1. トピックの紹介

1312. 文字列を回文にするための最小挿入数 文字
列 s を指定すると、各操作で文字列内の任意の位置に任意の文字を挿入できます。
s が回文文字列になるための最小操作数を返してください。
「回文文字列」とは、前から読んでも後ろから読んでも同じ文字列です。
ここに画像の説明を挿入します
ここに画像の説明を挿入します

2. 問題解決のアイデア

3.コード

class Solution {
    
    
public:
    int minInsertions(string s) {
    
    
        int n = s.size();
        //1.判断出字符串中最长回文子序列
        vector<int> v(n, 0);
        vector<vector<int>> dp(n, v);
        //dp[i][j]表示以i为结尾以j为开始的最长回文子序列元素个数
        //初始化
        for(int i = 0;i < n; ++i)
        {
    
    
            dp[i][i] = 1;
        }
        for(int i = 0;i < n; ++i)
        {
    
    
            for(int j = i - 1;j >= 0; --j)
            {
    
    
                if(s[i] == s[j])//如果相等,则回文子序列加2元素
                {
    
    
                    dp[i][j] = dp[i - 1][j + 1] + 2;
                }
                else//如果不相等,则它的回文子序列为i或j往前遍历一个位置对应的回文子序列的较大值
                {
    
    
                    dp[i][j] = max(dp[i - 1][j], dp[i][j + 1]);
                }
            }
        }
        int a = dp[n - 1][0];
        //2.用总元素个数减去最长回文子序列的元素个数
        return n - a;
    }
};

4. 走行結果

ここに画像の説明を挿入します

2. 1143. 最長共通部分列

1. トピックの紹介

1143. 最長共通部分列
2 つの文字列 text1 と text2 を指定すると、これら 2 つの文字列の最長共通部分列の長さを返します。共通の部分列がない場合は 0 を返します。
文字列のサブシーケンスとは、文字の相対的な順序を変更せずに、一部の文字を削除する (または文字をまったく削除しない) ことによって、元の文字列から構成される新しい文字列を指します。
たとえば、「ace」は「abcde」の部分列ですが、「aec」は「abcde」の部分列ではありません。
2 つの文字列の共通部分シーケンスは、両方の文字列が共通に持つ部分シーケンスです。
ここに画像の説明を挿入します

2. 問題解決のアイデア

3.コード

class Solution {
    
    
public:
    int longestCommonSubsequence(string text1, string text2) {
    
    
        vector<int> v(text2.size() + 1, 0);
        vector<vector<int>> dp(text1.size() + 1, v);
        //dp[i][j]表示以i - 1为结尾的text1字符串和以j - 1为结尾的text2这两个字符串的最长公共子序列(为啥要-1呢?为了方便计算i - 1和j - 1的值,而不用很麻烦的初始化i=0和j=0的情况,实际上就是将i和j作为了长度而不是坐标)
        for(int i = 1;i <= text1.size(); ++i)
        {
    
    
            for(int j = 1;j <= text2.size(); ++j)
            {
    
    
                if(text1[i - 1] == text2[j - 1])//如果i和j对应元素相等,就等于它们前一个元素对应的最长长度加一
                {
    
    
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                else//如果不相等就等于它们分别前一个元素对应的最长长度的较大值
                {
    
    
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[text1.size()][text2.size()];
    }
};

4. 走行結果

ここに画像の説明を挿入します

3. 1035. バラバラな線

1. トピックの紹介

1035. 連続しない行
nums1 と nums2 の整数を、指定された順序で 2 本の独立した水平線に書き込みます。
ここで、2 つの数値 nums1[i] と nums2[j] を結ぶ直線を描くことができます。これらの直線は、同時に nums1[i] == nums2[j] を満たす必要があり、描かれた直線は次の条件を満たしません
。交差する他の線 (水平線ではない) と接続します。
線は端点であっても交差できないことに注意してください。各数値は 1 つの線にのみ属することができます。
この方法で線を描画し、描画できる接続の最大数を返します。
ここに画像の説明を挿入します
ここに画像の説明を挿入します

2. 問題解決のアイデア

3.コード

class Solution {
    
    
public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
    
    
        vector<int> v(nums2.size() + 1, 0);
        vector<vector<int>> dp(nums1.size() + 1, v);
        //实际上就是在求:以i为结尾的nums1数组和以j结尾的nums2数组两者之间的最长公共子序列
        for(int i = 1;i <= nums1.size(); ++i)
        {
    
    
            for(int j = 1;j <= nums2.size(); ++j)
            {
    
    
                if(nums1[i - 1] == nums2[j - 1])
                {
    
    
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                else
                {
    
    
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[nums1.size()][nums2.size()];
    }
};

4. 走行結果

ここに画像の説明を挿入します


要約する

今日はアルゴリズム実習11日目です。
風や波が崩れることもありますが、帆を張って海を渡って頑張ってください。
この記事のタイトルの出典: LeetCode、著作権は LeetCode Network に属します。
この記事があなたにインスピレーションを与えたなら、著者をもっとサポートしていただければ幸いです。皆さん、ありがとう!

おすすめ

転載: blog.csdn.net/xjjxjy_2021/article/details/131455479
おすすめ