leetcode *718. 最長重複子數組

【題目】*718. 最長重複子數組

給兩個整數數組 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

【解題思路1】動態規劃

以[1, 2, 3, 2, 1]和[3,2,1,4]爲例
在這裏插入圖片描述
比較A[i] 、B[j],如果不相等,則公共子序列肯定不包括它們倆;如果相等,則它們兩至少可以組成長度爲1的子數組,然後繼續考慮它們前面的序列即 A[0]-A[i-1] 和 B[0]-B[j-1] 這兩個區間【能爲它們提供多大的公共長度】
比較A[i-1] 、B[j-1],如果不相等,則公共子序列肯定不包括它們倆;如果相等,則繼續考慮它們再前面的序列【能爲它們倆提供多大的公共長度】……
這就轉化爲子問題了

dp[i][j] 定義: 長度爲 i 以 A[i-1] 爲末尾的序列,和長度爲 j以 B[j-1] 爲末尾的序列,二者的最大公共後綴序列長度(該公共序列以A[i-1](B[j-1])爲末尾項)
邊界條件:i0 || j0 ,即其中一個長度爲0,是空子數組,沒有公共長度,dp[i][j] = 0
轉移方程:若A[i-1] == B[j-1],則dp[i][j] = dp[i - 1][j - 1] + 1,否則dp[i][j] = 0,最後答案即爲所有 dp[i][j] 中的最大值
注:從前往後即dp[0][0]往dp[lenA-1][lenB-1]計算,和從後往前,是一樣的

class Solution {
    public int findLength(int[] A, int[] B) {
        int max = 0;
        int lenA = A.length, lenB = B.length;
        int[][] dp = new int[lenA + 1][lenB + 1];
        for (int i = 1; i <= lenA; i++) {
            for (int j = 1; j <= lenB; j++) {
                if (A[i - 1] == B[j - 1])
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                else
                    dp[i][j] = 0;
                max = Math.max(max, dp[i][j]);
            }
        }
        return max;
    }
}

【解題思路2】滑動窗口

以[1, 2, 3, 2, 1]和[3,2,1,4]爲例
在這裏插入圖片描述
在這裏插入圖片描述

class Solution {
    public int findLength(int[] A, int[] B) {
        int aLength = A.length, bLength = B.length;
    //total是總共運行的次數
        int total = aLength + bLength - 1;
        int max = 0;
        for (int i = 0; i < total; i++) {
    //判斷數組A和數組B比較的起始位置和比較的長度
            int aStart = 0;
            int bStart = 0;
            int len = 0;
            if (i < aLength) {
                aStart = aLength - i - 1;
                bStart = 0;
                len = i + 1;
            } else {
                aStart = 0;
                bStart = i - aLength+1;
                len = Math.min(bLength - bStart, aLength);
            }
            int maxlen = maxLength(A, B, aStart, bStart, len);
            max = Math.max(max, maxlen);
        }
        return max;
    }
    //計算A和B在上面圖中紅色框內的最大長度
    public int maxLength(int[] A, int[] B, int aStart, int bStart, int len) {
        int max = 0, count = 0;
        for (int i = 0; i < len; i++) {
            if (A[aStart + i] == B[bStart + i]) {
                count++;
                max = Math.max(max, count);
            } else {
                count = 0;
            }
        }
        return max;
    }
}

分開寫,感覺會好理解一點區間到底是怎麼取的

class Solution {
    public int findLength(int[] A, int[] B) {
        int n = A.length, m = B.length;
        int ret = 0;
        for (int i = 0; i < n; i++) {
            int len = Math.min(m, n - i);
            int maxlen = maxLength(A, B, i, 0, len);
            ret = Math.max(ret, maxlen);
        }
        for (int i = 0; i < m; i++) {
            int len = Math.min(n, m - i);
            int maxlen = maxLength(A, B, 0, i, len);
            ret = Math.max(ret, maxlen);
        }
        return ret;
    }

    public int maxLength(int[] A, int[] B, int addA, int addB, int len) {
        int ret = 0, k = 0;
        for (int i = 0; i < len; i++) {
            if (A[addA + i] == B[addB + i]) {
                k++;
            } else {
                k = 0;
            }
            ret = Math.max(ret, k);
        }
        return ret;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章