日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

每日题解:LeetCode 718. 最长重复子数组

發(fā)布時間:2024/1/8 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 每日题解:LeetCode 718. 最长重复子数组 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目地址
個人博客地址

題目描述

給兩個整數(shù)數(shù)組 A 和 B ,返回兩個數(shù)組中公共的、長度最長的子數(shù)組的長度。

示例:輸入: A: [1,2,3,2,1] B: [3,2,1,4,7] 輸出:3 解釋: 長度最長的公共子數(shù)組是 [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;} };

解題思路

最簡單的寫法是三層循環(huán),逐步對比字符是否相等,然后往后遍歷,

for(){ for(){ while(){}} }

但是這題的測試用例會出現(xiàn)超時的問題,所以就需要減少循環(huán)的次數(shù)

滑動窗口


出處:小馬的筆記

我覺的這個gif能很好的表示滑動窗口的做法
1.先固定A,移動 B,逐個尋找公共子數(shù)組中的長度
2.反之,固定B,移動A,尋找公共子數(shù)組中的長度
3.對比尋找處最大的公共子數(shù)組長度

for (int i = 0; i < lenA; ++i) {int len = Math.min(lenB, lenA - i);//先固定B的位置,即B數(shù)組的下標(biāo)為0int maxLen = finMaxLen(A, B, i, 0, len);ans = Math.max(ans, maxLen);}/*** Solution:: finMaxLen* <p>尋找len長度內(nèi),兩個數(shù)組的最長公共子數(shù)組/p>* <p>HISTORY: 2020/7/1 liuha : Created.</p>* @param A A數(shù)組* @param B B數(shù)組* @param addA A數(shù)組的滑動開始的下標(biāo),0下標(biāo)表示當(dāng)前數(shù)組為固定的數(shù)組* @param addB B數(shù)組的滑動開始的下標(biāo),0下標(biāo)表示當(dāng)前數(shù)組為固定的數(shù)組* @param len* @return 最長公共子數(shù)組的長度長度*/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;}

這個思路又借鑒官方的寫法,我覺得官方的寫法更優(yōu)雅,這里將時間復(fù)雜度降到了O((N+M)×min(N,M)),
但我們遍歷完A數(shù)組別忘記,還要固定A數(shù)組,遍歷B數(shù)組

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);}

DP

我們假設(shè)dp[i][j] 表示 A[] 和 B[]的最長公共前綴,i,j分別是數(shù)組的下標(biāo),那么答案即為所有 dp[i][j] 中的最大值。
我們以示例

A: [1,2,3,2,1] B: [3,2,1,4,7]

如表格所示,我們需要的在坐標(biāo)為 (0,2)(1,3)(2,4)

12321A數(shù)組
31
211
111
4
7
B數(shù)組

存在的規(guī)律
1.下標(biāo)存在dp[i][j]–>dp[i+1][j+1]->dp[i+2][j+2]
2.如圖中箭頭指向,當(dāng)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的狀態(tài)公式了
dp[i][j]=dp[i+1][j+1]+1 if(A[i]==B[j])
由于dp[i][j]從``dp[i+1][j+1]得到,所以我們要反過來遍歷數(shù)組

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]);}}

或者使用另一個狀態(tài)公式遍歷

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]);}}}

總結(jié)

以上是生活随笔為你收集整理的每日题解:LeetCode 718. 最长重复子数组的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。