1. 程式人生 > >Maximum Length of Repeated Subarray 最長重複子陣列

Maximum Length of Repeated Subarray 最長重複子陣列

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

示例 1:

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

說明:

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

思路:

採用動態規劃,通過維護一個二維陣列dp來計算最長重複子陣列。如下圖例子所示:

  3 1 2
1 0 1 0
2 0 0 2
2 0 0 1

行表示A,列表示B,dp[i][j]的值為如果A[i]和B[j]相等,則dp[i][j]等於他左上角的值+1,否則等於0。

參考程式碼如下:

    int findLength(vector<int>& A, vector<int>& B) {
	int m = A.size();
	int n = B.size();
	if (!m || !n) {
		return 0;
	}
	vector<vector<int>> dp(m+1,vector<int>(n+1,0));
	int res = 0;
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			dp[i][j] = (A[i - 1] == B[j - 1]) ? dp[i - 1][j - 1] + 1 : 0;
			res = max(res, dp[i][j]);
		}
	}
	return res;        
    }

思路2:本文可以簡化為O(n+1)的複雜度,即只需要一個一維陣列,由於我們要考慮到陣列元素覆蓋的問題,所以遞迴公式改為:

/**
 * dp[i][j] = a[i] == b[j] ? dp[i + 1][j + 1] : 0;
 * dp[i][j] : max lenth of common subarray start at a[i] & b[j];
 */

且遍歷A和B的方式發生了改變,如下圖所示(綠線所示):


參考程式碼如下:

    int findLength(vector<int>& A, vector<int>& B) {
	int m = A.size();
	int n = B.size();
	if (!m || !n) {
		return 0;
	}
	vector<int> dp(n+1,0);
	int res = 0;
	for (int i = m-1; i >=0; i--) {
		for (int j = 0; j < n; j++) {
			dp[j] = (A[i] == B[j]) ? dp[j + 1] + 1 : 0;
			res = max(res, dp[j]);
		}
	}
	return res;     
    }