題目
給兩個整數數組 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
鏈接:https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray
解題記錄
- 通過構建B的映射表,數值和index的關係
- 通過循環遍歷A獲取B中位置進行比較獲取最長
/**
* @author ffzs
* @describe
* @date 2020/7/1
*/
public class Solution {
public static int findLength(int[] A, int[] B) {
int res = 0;
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < B.length; i++) {
if (!map.containsKey(B[i])) {
List<Integer> lst = new ArrayList<>();
lst.add(i);
map.put(B[i], lst);
}
else {
map.get(B[i]).add(i);
}
}
for (int i = 0; i < A.length; i++) {
if (map.containsKey(A[i]) && i+res < A.length) {
for (Integer it : map.get(A[i])) {
res = Math.max(res, matchLen(A, B, i, it));
}
}
}
return res;
}
private static int matchLen (int[] A, int[] B, int sa, int sb) {
int len = 0;
int i = sa, j = sb;
while (i < A.length && j < B.length) {
if (A[i++] == B[j++]) {
len ++;
}
else break;
}
return len;
}
public static void main(String[] args) {
int[] A = {1,2,3,2,1};
int[] B = {3,2,1,4,7};
// System.out.println(matchLen(A, B, 0, 1));
System.out.println(findLength(A, B));
}
}
因爲會有連續重複的情況出現,這時每一個重複的都進行比對的話就比較費時
動態規劃
- 通過動態規劃
dp[i][j]=dp[i-1][j-1] + 1
- 每次獲得之後更新res值
- 如果從後向前比較的話可以只需要上一層的dp值,因此可以使用
dp[]
代替dp[][]
/**
* @author ffzs
* @describe
* @date 2020/7/1
*/
public class Solution3 {
public static int findLength(int[] A, int[] B) {
int res = 0;
int[] dp = new int[B.length + 1];
for (int i = 0; i < A.length; i++) {
for (int j = B.length; j >= 1 ; --j) {
if (A[i] == B[j-1]) {
dp[j] = dp[j-1] + 1;
res = Math.max(dp[j], res);
}
else dp[j] = 0;
}
}
return res;
}
public static void main(String[] args) {
int[] A = {1,2,3,2,1};
int[] B = {3,2,1,4,7};
System.out.println(findLength(A, B));
}
}
滑動窗口
- 通過移動A進行錯位,兩數組重合部分爲窗口
- 對窗口中的兩個數組進行匹配,獲得每個窗口的最大匹配個數
- 進而獲得總的最大
/**
* @author ffzs
* @describe
* @date 2020/7/1
*/
public class Solution4 {
public static int findLength(int[] A, int[] B) {
int res = 0;
// 保證 A 短
if (A.length > B.length) {
int[] tmp = A;
A = B;
B = tmp;
}
int ia = A.length - 1, ib = 0 , len = 1;
while (ib != B.length) {
if (len > res) res = Math.max(matchLen(A, B, ia, ib, len), res);
if (ib == 0 && ia != 0){
ia --;
len = A.length - ia;
}
else {
ib++;
len = Math.min(A.length, B.length-ib);
}
}
return res;
}
private static int matchLen (int[] A, int[] B, int ai, int bi, int len) {
int count = 0, ret = 0;
for (int i = 0; i < len; i++) {
if (A[ai + i] == B[bi + i]){
count++;
ret = Math.max(ret, count);
}
else count = 0;
}
return ret;
}
public static void main(String[] args) {
int[] A = {1,2,3,2,1};
int[] B = {3,2,1,4,7};
System.out.println(findLength(A, B));
}
}