アルゴリズム学習|動的プログラミング LeetCode 300. 最長のインクリメンタル サブシーケンス、674. 最長の連続インクリメンタル シーケンス、718. 最長の繰り返しサブアレイ

1. 最長増加サブシーケンス

与えられた整数 nums の配列で、その中で最も長く厳密に増加するサブシーケンスの長さを見つけます。
サブシーケンスは、残りの要素の順序を変更せずに要素が削除された (または削除されなかった) 配列から派生したシーケンスです。たとえば、[3,6,2,7] は配列 [0,3,1,6,2,2,7] のサブシーケンスです。

一連の考え

1.dp[i]: nums[i] で終わる最長の増加サブシーケンスの長さを示します
2. 再帰式: dp[i] = max(dp[j] + 1,dp[i]) j は 0 から i まで移動します-1
3. 初期化: dp[i] = 1 各 i について、対応する dp[i] の開始サイズは少なくとも 1 です 4.
走査順序: 前から後ろへ走査
最終結果: 各 nums[i] まで走査最後に最も長く増加するサブシーケンスの長さ、最大値を見つける

実装コード

class Solution {
    
    
public:
    int lengthOfLIS(vector<int>& nums) {
    
    
        if(nums.size() <= 1) return nums.size();
        vector<int> dp(nums.size(),1);
        int result = 0;
        for(int i = 1; i < nums.size(); i++) {
    
    
            for(int j = 0; j < i; j++) {
    
    
                if(nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
            }
            if(dp[i] > result) result = dp[i];
        }
        return result;
    }
};

2. 最長の連続増加シーケンス

整数のソートされていない配列を指定して、連続的に増加する最長のサブシーケンスを見つけ、そのシーケンスの長さを返します。

一連の考え

1. dp[i]: i で終わる最長の増加サブシーケンスの長さを示します
2. 再帰式: if(nums[[i] > nums[i - 1]) dp[i] = dp[i - 1] + 1 (連続)
3. 初期化: dp[i] = 1
4. 走査順序: 前から後ろへ走査

実装コード

class Solution {
    
    
public:
    int findLengthOfLCIS(vector<int>& nums) {
    
    
        if(nums.size() <= 1) return nums.size();
        vector<int> dp(nums.size(), 1);
        int result = 0;
        for(int i = 1; i < nums.size(); i++) {
    
    
            if(nums[i] > nums[i - 1]) dp[i] = dp[i - 1] + 1; 
            if(dp[i] > result) result = dp[i];
        }
        return result;
    }
};

3. 最長繰り返し部分配列

2 つの整数配列 A と B を指定して、両方の配列に共通する最長の部分配列の長さを返します。
サブ配列は、サブ配列の連続したシーケンスです

一連の考え

1.dp[i][j]: nums1 は i-1 で終わり、nums2 は j-1 で終わり、最も長く繰り返される部分配列の長さは dp[i][j] です。

dp[i][j] が添字 i で終わる A と添字 j で終わる B として定義されている場合、nums1[i] が nums2[0] と同じ場合、最初の行と最初の列が初期化されます。 、対応する dp[i][0] は最初は 1 になります。これは、この時点で最も長く繰り返されるサブ配列が 1 であるためです。nums2[j] が nums1[0] と同じ場合、同じです。

2. 再帰式: if(nums[i- 1] == nums[j- 1]) dp[i][j] = dp[i - 1][j- 1] +1 3. 初期化: dp [
i ][0] = 0 dp[0][j] = 0 他の添字配列は 0 に初期化されます
4. 走査順序: nums1/nums2 を走査し、次に nums2/nums1 を走査します
最終結果: すべての 2 次元配列を走査し、最も長い配列を見つけます子配列の繰り返し

実装コード

class Solution {
    
    
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
    
    
        vector<vector<int>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1, 0));
        int result = 0;
        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;
                }
                if(dp[i][j] > result) result = dp[i][j];
            }
        }
        return result;
    }
};

おすすめ

転載: blog.csdn.net/li26324949/article/details/130015538