leetcode718. 最長重複子數組/動態規劃,滑動窗口

題目:leetcode718. 最長重複子數組/動態規劃

給兩個整數數組 A 和 B ,返回兩個數組中公共的、長度最長的子數組的長度。

示例 1:

輸入:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
輸出: 3
解釋: 
長度最長的公共子數組是 [3, 2, 1]

說明:

  • 1 <= len(A), len(B) <= 1000
  • 0 <= A[i], B[i] < 100

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

基本思想1:動態規劃

  • dp[i][j]:以 A[i - 1]結束的子數組 和 B[j - 1]結束的子數組的最長匹配的個數,因爲這裏是子數組每個元素要連續(區別:子序列,子序列不連續)
  • 狀態:兩個數組中的每一個字符
  • 選擇:是否包含當前元素
  • 狀態轉移方程:當前兩個元素相等,dp[i][j] = 1 + dp[i - 1][j - 1];不相等:dp[i][j] = dp[i - 1][j - 1]

說明:如果是最長子序列,dp數組的含義和狀態轉移方程均不一樣

  • dp[i][j]:A的前 i 個字符和B的前 j 個字符最長匹配的子序列
  • 狀態轉移方程:dp[i][j]=max(dp[i1][j1]+(A[i1]==B[j1]?1:0),dp[i1][j],dp[i][j1])dp[i][j] = max(dp[i - 1][j - 1] + (A[i - 1] == B[j - 1] ? 1 : 0),dp[i - 1][j], dp[i][j - 1])

時間複雜度:O(N * M)

class Solution {
public:
    int findLength(vector<int>& A, vector<int>& B) {
        //動態規劃
        vector<vector<int>> dp(A.size() + 1, vector<int>(B.size() + 1, 0));
        int res = 0;
        for(int i = 1; i <= A.size(); ++i){
            for(int j = 1; j <= B.size(); ++j){
                if(A[i - 1] == B[j - 1]){
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                res = max(res, dp[i][j]);
                //cout << dp[i][j] << " ";
            }
            //cout << endl;
        }
        return res;
    }
};

基本思想2:滑動窗口

該思想是基於:最長子數組在兩個數組中的位置不一定相同,於是可以採取根據兩數組的不同對齊方式取找最長子數組
下述代碼中分兩步進行:

  • 首先是A不變,B的首元素依次和A中的某個元素對齊,求解最長的重複子數組,求解的過程中如果兩個字符相等,遞增變量;否則,將變量置爲0,在這個過程中要不斷更新結果數組
  • 然後是B不變,A的首元素依次和B中的某個元素對齊。接下來的過程是一樣的

時間複雜度:O((N +M)* min(N,M))

class Solution {
public:
    int findLength(vector<int>& A, vector<int>& B) {
        //滑動窗口
        int res = 0, cur, k;
        for(int i = 0; i < A.size(); ++i){//以A爲基準,滑動B
            cur = 0;
            k = i;
            for(int j = 0; j < B.size() && k < A.size(); ++j,++k){
                if(A[k] == B[j])
                    ++cur;
                else
                    cur = 0;
                res = max(res, cur);
            }
            
        }
        for(int i = 0; i < B.size(); ++i){//以B爲基準,滑動A
            cur = 0;
            k = i;
            for(int j = 0; j < A.size() && k < B.size(); ++j, ++k){
                if(B[k] == A[j])
                    ++cur;
                else
                    cur = 0;
                res = max(res, cur);
            }
            
        }
        return res;
    }
    
};

基本思想3:暴力

求數組A中從 i 開始和數組B中從 j 開始的最長重複子數組,時間複雜度爲O(n3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章