每日题解:LeetCode 718. 最长重复子数组
題目地址
個人博客地址
題目描述
給兩個整數數組 A 和 B ,返回兩個數組中公共的、長度最長的子數組的長度。
示例:輸入: 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
解法
JAVA
class Solution {public int findLength(int[] A, int[] B) {int lenA = A.length;int lenB = B.length;int ans = 0;for (int i = 0; i < lenA; ++i) {int len = Math.min(lenB, lenA - i);int maxLen = finMaxLen(A, B, i, 0, len);ans = Math.max(ans, maxLen);}for (int i = 0; i < lenB; ++i) {int len = Math.min(lenA, lenB - i);int maxLen = finMaxLen(A, B, 0, i, len);ans = Math.max(ans, maxLen);}return ans;}private int finMaxLen(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;} }CPP
class Solution { public:static int findLength(vector<int> &A, vector<int> &B) {//DP[i][j]int ans = 0;int lenA = A.size();int lenB = B.size();vector<vector<int>> dp(lenA + 1, vector<int>(lenB + 1, 0));for (int i = lenA - 1; i >= 0; i--) {for (int j = lenB - 1; j >= 0; j--) {dp[i][j]=A[i]==B[j]?dp[i+1][j+1]+1:0;ans=max(ans, dp[i][j]);}}return ans;} };解題思路
最簡單的寫法是三層循環,逐步對比字符是否相等,然后往后遍歷,
for(){ for(){ while(){}} }但是這題的測試用例會出現超時的問題,所以就需要減少循環的次數
滑動窗口
出處:小馬的筆記
我覺的這個gif能很好的表示滑動窗口的做法
1.先固定A,移動 B,逐個尋找公共子數組中的長度
2.反之,固定B,移動A,尋找公共子數組中的長度
3.對比尋找處最大的公共子數組長度
這個思路又借鑒官方的寫法,我覺得官方的寫法更優雅,這里將時間復雜度降到了O((N+M)×min(N,M)),
但我們遍歷完A數組別忘記,還要固定A數組,遍歷B數組
DP
我們假設dp[i][j] 表示 A[] 和 B[]的最長公共前綴,i,j分別是數組的下標,那么答案即為所有 dp[i][j] 中的最大值。
我們以示例
如表格所示,我們需要的在坐標為 (0,2)(1,3)(2,4)
| 3 | 1 | |||||
| 2 | 1 | 1 | ||||
| 1 | 1 | 1 | ||||
| 4 | ||||||
| 7 | ||||||
| B數組 |
存在的規律
1.下標存在dp[i][j]–>dp[i+1][j+1]->dp[i+2][j+2]
2.如圖中箭頭指向,當A[i]==B[j]時dp[i][j]=dp[i+1][j+1]+1,或者理解為A[i-1]==B[j-1]時dp[i][j]=dp[i-1][j-1]+1,
那就可以整理處DP的狀態公式了
dp[i][j]=dp[i+1][j+1]+1 if(A[i]==B[j])
由于dp[i][j]從``dp[i+1][j+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] = 1 + dp[i - 1][j - 1];ans = max(ans, dp[i][j]);}}}總結
以上是生活随笔為你收集整理的每日题解:LeetCode 718. 最长重复子数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java工厂方法_Java设计模式之工厂
- 下一篇: Android应用内社区SDK技术架构浅