Leetcode:NO.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

鏈接: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));
    }
}

在這裏插入圖片描述

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