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

      歡迎訪問 生活随笔!

      生活随笔

      當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

      编程问答

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

      發布時間:2024/1/8 编程问答 24 豆豆
      生活随笔 收集整理的這篇文章主要介紹了 每日题解: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.對比尋找處最大的公共子數組長度

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

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

      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

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

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

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

      12321A數組
      31
      211
      111
      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 = 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]);}}

      或者使用另一個狀態公式遍歷

      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. 最长重复子数组的全部內容,希望文章能夠幫你解決所遇到的問題。

      如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。