package class51; import java.util.HashMap; public class Problem_1035_UncrossedLines { // 针对这个题的题意,做的动态规划 public static int maxUncrossedLines1(int[] A, int[] B) { if (A == null || A.length == 0 || B == null || B.length == 0) { return 0; } int N = A.length; int M = B.length; // dp[i][j]代表: A[0...i]对应B[0...j]最多能划几条线 int[][] dp = new int[N][M]; if (A[0] == B[0]) { dp[0][0] = 1; } for (int j = 1; j < M; j++) { dp[0][j] = A[0] == B[j] ? 1 : dp[0][j - 1]; } for (int i = 1; i < N; i++) { dp[i][0] = A[i] == B[0] ? 1 : dp[i - 1][0]; } // 某个值(key),上次在A中出现的位置(value) HashMap AvalueLastIndex = new HashMap<>(); AvalueLastIndex.put(A[0], 0); // 某个值(key),上次在B中出现的位置(value) HashMap BvalueLastIndex = new HashMap<>(); for (int i = 1; i < N; i++) { AvalueLastIndex.put(A[i], i); BvalueLastIndex.put(B[0], 0); for (int j = 1; j < M; j++) { BvalueLastIndex.put(B[j], j); // 可能性1,就是不让A[i]去划线 int p1 = dp[i - 1][j]; // 可能性2,就是不让B[j]去划线 int p2 = dp[i][j - 1]; // 可能性3,就是要让A[i]去划线,那么如果A[i]==5,它跟谁划线? // 贪心的点:一定是在B[0...j]中,尽量靠右侧的5 int p3 = 0; if (BvalueLastIndex.containsKey(A[i])) { int last = BvalueLastIndex.get(A[i]); p3 = (last > 0 ? dp[i - 1][last - 1] : 0) + 1; } // 可能性4,就是要让B[j]去划线,那么如果B[j]==7,它跟谁划线? // 贪心的点:一定是在A[0...i]中,尽量靠右侧的7 int p4 = 0; if (AvalueLastIndex.containsKey(B[j])) { int last = AvalueLastIndex.get(B[j]); p4 = (last > 0 ? dp[last - 1][j - 1] : 0) + 1; } dp[i][j] = Math.max(Math.max(p1, p2), Math.max(p3, p4)); } BvalueLastIndex.clear(); } return dp[N - 1][M - 1]; } // 但是其实这个题,不就是求两个数组的最长公共子序列吗? public static int maxUncrossedLines2(int[] A, int[] B) { if (A == null || A.length == 0 || B == null || B.length == 0) { return 0; } int N = A.length; int M = B.length; int[][] dp = new int[N][M]; dp[0][0] = A[0] == B[0] ? 1 : 0; for (int j = 1; j < M; j++) { dp[0][j] = A[0] == B[j] ? 1 : dp[0][j - 1]; } for (int i = 1; i < N; i++) { dp[i][0] = A[i] == B[0] ? 1 : dp[i - 1][0]; } for (int i = 1; i < N; i++) { for (int j = 1; j < M; j++) { int p1 = dp[i - 1][j]; int p2 = dp[i][j - 1]; int p3 = A[i] == B[j] ? (1 + dp[i - 1][j - 1]) : 0; dp[i][j] = Math.max(p1, Math.max(p2, p3)); } } return dp[N - 1][M - 1]; } }