當僅使用 2 * min(m, n) 個條目和 o(1) 個額外空間計算 LCS(最長公共子序列)的長度時,我們可以使用滾動陣列技術。 此方法的核心思想是僅使用上一行的資料填充 dp 表,因為當前行中的資料僅依賴於上一行中的資料。 這樣我們就可以避免儲存整個二維陣列而只儲存一行。
首先,我們建立乙個長度為 n + 1 的陣列 dp,其中 dp[j] 表示 str1 的前 i 個字元和 str2 的前 j 個字元的 LCS 長度。 由於我們只需要上一行的資料,因此我們可以在計算新行時覆蓋舊行的資料。
下面是使用 go 的實現示例:
package main import ( "fmt") func lcslength(str1, str2 string) int padding dp table for i := 1; i <= m;i++ else prev = curr } 返回 lcs 返回 dp[n] }func max(a, b int) int return b } func main() 的長度。
現在,為了進一步優化空間複雜度以僅使用 min(m, n) 個條目和 o(1) 個額外空間,我們可以使用兩個 min(m, n) +1 的陣列來交替儲存每行的資料。 這可以通過乙個額外的變數來完成,以跟蹤當前正在使用的陣列。
下面是使用 go 的實現示例:
package main import ( "fmt") func lcslength(str1, str2 string) int 交替更新 i 的 dp 表 := 1 使用兩個陣列交替更新; i <= m;i++ else prev = curr } swap array dp1, dp2 = dp2, dp1 } else return b}func lcslength(x, y int) int c := make(int, n+1) for i := 0; i <= m; i++ else if x[i-1] == y[j-1] else }return c[n]}func main() y := int fmt.println("length of lcs is", lcslength(x, y))}
在這個程式中,我們只保留當前行和上一行的資料,並用變數 last 和 curr 標記這兩行。 在每次迭代中,我們將 curr 的值設定為 1-last,然後將 last 的值設定為 curr。 這允許我們在每次迭代時交換 curr 和 last 的值,這樣我們就可以只用 min(m,n) 個條目和 o(1) 的額外空間來做同樣的事情。
在此處插入說明。
在此處插入說明。
我們可以修改前面的 memo 方法,僅使用 2min(m, n) 個條目和 o(1) 個額外的空格。 讓我們從建立乙個二維陣列 c 開始,其中 c[i][j] 儲存 x[0....i] 和 y[0....J]. 然後,我們使用兩個指標 i 和 j 在 x 和 y 中移動,計算每個 c[i][j] 的值。 移動指標時,我們只需要保留上一行和當前行的條目,這樣我們就可以使用 2min(m, n) 個條目。
以下是它在 GO 中的作用:
package main func lcslength(x string, y string, m int, n int) int c := make(int, m+1) for i := range c for i := 1; i <= m; i++ else }return c[m][n]} func max(a, b int) int return b } func main()
為了只使用 min(m, n) 條目和 o(1) 的額外空間,我們可以稍微修改上面的方法。 我們仍然使用二維陣列 c,但這次我們只保留當前行的條目。 移動指標時,我們只需要保留當前行中的左右條目,這樣我們就可以使用 min(m, n) 條目。
以下是它在 GO 中的作用:
package main func lcslength(x string, y string, m int, n int) int c := make(int, n+1) for i := 1; i <= m; i++ else if c[j] >right if i > m-j+1 }return right } func max(a, b int) int return b } func main()
在本例中,我們使用兩個變數 left 和 right 分別表示當前行中最左邊和最右邊的條目。 當我們遍歷 y 時,我們不斷更新這兩個變數,並在末尾返回,即 x 和 y 的 LCS 長度。
在此處插入說明。
在此處插入說明。
在此處插入說明。
首先,讓我們解釋如何使用 2*min(m, n) 條目和 o(1) 的額外空間計算最長公共子序列 (LCS) 的長度。 這個問題可以使用動態規劃來解決。 動態規劃是一種將問題分解為更小的子問題並儲存這些子問題的解決方案以避免重複計算的方法。
我們可以定義乙個二維陣列 dp[i][j],其中 dp[i][j] 表示字串 x 的前 i 個字元和字串 y 的前 j 個字元的最長公共子序列的長度。 然後,我們可以根據以下規則填充此陣列:
1.如果 x[i] == y[j],則 dp[i][j] = dp[i-1][j-1] +1。
2.如果 x[i]!= y[j],則 dp[i][j] = max(dp[i-1][j], dp[i][j-1])。
為了僅使用 2*min(m, n) 條目,我們只能將資料儲存在 min(m, n) 行和 min(m, n) 列中,因為其他資料可以通過填充規則從這些資料中推導出來。
現在,讓我們使用 go 語言來實現這個演算法:
package mainimport ( "fmt"func lcslength(x string, y string) int minlen := min(m, n) 初始化 dp 陣列 dp := make(int, minlen+1) for i := range dp padding dp array for i := 1; i <= m; i++ else }return dp[m][n]}func min(a, b int) int return b}func max(a, b int) int return b}func main()
接下來,我們將解釋如何僅使用 min(m, n) 條目和 o(1) 的額外空間來做同樣的事情。 我們可以通過從後到前填充動態程式設計陣列來做到這一點。 這樣,我們只需要儲存一行或一列資料,因為可以從填充規則中推導出其他資料。
以下是它在 GO 中的作用:
package mainimport ( "fmt")func lcslength(x string, y string) int minlen := min(m, n) 初始化 dp 陣列 var dp int dp = make(int, minlen+1) 從後到前填充 dp 陣列 i := n; i >= 1; i-- else prev =
在此處插入說明。
在此處插入說明。
在此處插入說明。
to compute the length of the longest common subsequence (lcs) using only 2*min(m, n) space plus o(1) additional space, you can use a technique called space optimization in the dp approach. here's a go implementation that demonstrates how to achieve this by only filling in necessary cells in the dp table:
package mainimport "fmt"// lcslength computes the length of the lcs using space optimization.func lcslength(x, y string) int if dp[idx] >0 len1 := lcslength(xidx-1, yidx) len2 := lcslength(xidx, yidx-1) if x[xidx-1] == y[yidx-1] else }// tr**erse the strings in the order that minimizes the space complexity. // this is achieved by starting with the longer string and then the shorter one. if m > n }else }return dp[idx]}// max returns the larger of two integers.func max(a, b int) int return b}func main()
this implementation **oids filling the entire dp table by only working on the cells that contribute to the lcs length. the lcslength function is the recursive part that calculates the length at each position, updating the dp array and the current index idx.
to reduce the space usage further, to just min(m, n) space plus o(1) additional space, you can use a stack or a queue to keep track of the indices instead of the dp array. however, this approach would require a more complex recursive function that maintains the stack or queue, which could make the code less clear.
the above code is optimized for space complexity, but due to its recursive nature, it may use more stack space than an iterative version. an iterative implementation with a stack could be used to ensure that the space complexity is truly o(1), but it would be more complex and likely not provide any significant performance improvements unless you are dealing with extremely large strings.
在此處插入說明。
在此處插入說明。
在此處插入說明。
在解釋如何使用 2*min(m,n) 條目和表 C 中 O(1) 的額外空間計算 LCS 長度之前,讓我們先了解一下 LCS(最長公共子序列)的概念。
LCS 問題有兩個序列 x 和 y,以找到最長的公共子序列。 子序列是通過從原始序列中刪除多個元素而獲得的新序列,不需要刪除元素的相對位置。 例如,序列 X:ABCD,序列 Y:ACDF,它們的 LCS 是 ACD。
以下是基於 2*min(m,n) 個條目和 o(1) 個額外空格的解決方案:
1.初始化分別指向序列 x 和 y 開頭的兩個指標 i 和 j。 2.建立乙個大小為 2*min(m,n) 的陣列 c 以儲存臨時計算結果。 3.對於每個 i 和 j,依次比較 x[i] 和 y[j] 的元素:如果 x[i] 和 y[j] 相等,則將 c[(i-1)%2][j%2] 的值乘以 1,並將 c[i%2][j%2] 更新為 c[(i-1)%2][j%2] 的值。 否則,將 c[i%2][j%2] 更新為 c[i%2][(j-1)%2] 和 c[(i-1)%2][j%2] 中的較大值。 4.返回 C[(M-1)%2][N%2] 作為 LCS 的長度。 下乙個解決方案是僅使用 min(m,n) 個條目和 o(1) 個額外的空格:
1.初始化 min(m,n) 的指標 i 和陣列 c 以儲存臨時計算的結果。 2.對於每個 i,依次比較 x[i] 和 y[i] 的元素:如果 x[i] 和 y[i] 相等,則將 c[i] 的值加 1,並將 c[i] 更新為 c[i-1] 的值。 否則,將 c[i] 更新為 c[i-1] 和 c[i] 中的較大值。 3.返回 C[min(m,n)-1] 作為 LCS 的長度。 下面是使用 Go 語言實現上述兩種演算法的示例:
package mainimport ( "fmt")func lcslengthusing2tables(x, y string, m, n int) int for i := 0; i <= m; i++ else if x[i-1] == y[j-1] else }return c[m%2][n%2]}func lcslengthusing1table(x, y string, m, n int) int else prev = temp } return c[n]}func max(a, b int) int return b}func main()
希望以上答案對您有所幫助! 如果您有任何問題,請隨時提問。
在此處插入說明。
在此處插入說明。
在此處插入說明。
要僅使用 2*min(m, n) 表條目計算 LCS 的長度,您可以使用滾動陣列的概念。 這是它在 Go 中的樣子:
package mainimport ( "fmt")func lcslength(x, y string) int c := make(int, 2*n+1) 表 c 只需要 2*min(m,n) 個條目 i := 0; i <= m; i++ else if x[i-1] == y[j-1] else if c[prevrow*(n+1)+j] >= c[currrow*(n+1)+j-1] else }return c[m%2*(n+1)+n]}func main()
此**使用滾動陣列來儲存計算結果,從而減少條目數。 在每次迭代中,只保留當前行和上一行的結果,並通過模運算確定相應的索引位置。 最後,將表C中(m%2)*(n+1)+n對應的值作為LCS的長度返回。
要僅使用 min(m, n) 個條目執行相同的工作,並使用 o(1) 的額外空間,您可以使用貪婪演算法。 這是它在 Go 中的樣子:
package mainimport ( "fmt")func lcslength(x, y string) int currrow := make(int, n+1) prevrow := make(int, n+1) for i := 0; i <= m; i++ else if x[i-1] == y[j-1] else if prevrow[j] >= currrow[j-1] else }copy(prevrow, currrow) }return currrow[n]}func main()
**使用prevrow和currrow兩個陣列來儲存計算結果,每次迭代只需要訪問上一行的資料。 通過複製陣列來更新當前行的結果。 最終返回 currrow[n] 作為 LCS 的長度。
這兩種方法都可用於計算 LCS 長度,具有更少的條目和額外的空間。
在此處插入說明。
在此處插入說明。
在此處插入說明。
為了計算兩個序列的最長公共子序列(LCS)的長度,我們可以使用動態規劃的方法。 在標準動態規劃方法中,我們使用二維陣列 dp 來儲存子問題的解,其中 dp[i][j] 表示序列 x 的前 i 個元素和序列 y 的前 j 個元素的 LCS 長度。 該方法的空間複雜度為 o(m * n)。
為了降低空間複雜性,我們可以使用滾動陣列技術,該技術僅保留計算當前和先前狀態所需的資訊。 通過這種方式,我們可以將空間複雜度降低到 o(min(m, n))。 以下是在 go 語言中實現此方法的方法**:
package mainimport ( "fmt"lcs 函式計算兩個序列的最長公共子序列的長度func lcs(x, y string) int 建立乙個大小為 min(m, n) +1 dp 的一維陣列 := make(int, n+1) for i := 1; i <= m;i++ else } 返回最長的公共子序列的長度 return dp[n]} max 返回兩個整數的最大值 func max(a, b int) int return b}func main().
在此實現中,我們首先確保 x 是乙個較短的序列。 然後,我們建立乙個大小為 n+1(n 是 y 的長度)的一維陣列 dp。 在計算過程中,我們只更新 dp 陣列的當前和以前的狀態。 這樣,我們就不需要儲存 m * n 的整個二維陣列,從而將空間複雜度降低到 o(min(m, n))。
在僅使用 min(m, n) 條目的情況下,我們可以使用兩個一維陣列 prev 和 curr 來交替儲存有關先前和當前狀態的資訊。 這種方法的時間複雜度仍為o(m * n),但空間複雜度降低到o(min(m, n))。 下面是實現此方法的 go 語言:
package mainimport ( "fmt"lcs 函式計算兩個序列的最長公共子序列的長度func lcs(x, y string) int 建立兩個一維陣列,每個陣列的大小為 n+1 prev := make(int, n+1) curr := make(int, n+1) for i := 1; i <= m;i++ else } swap prev and curr prev, curr = curr, prev } 返回最長的公共子序列的長度 return prev[n]} max 返回兩個整數的最大值 func max(a, b int) int return b}func main().
在此實現中,我們使用兩個一維陣列 prev 和 curr 來交替儲存有關先前和當前狀態的資訊。 在每次迭代中,我們都會更新 curr 陣列,並在迭代結束時交換 prev 和 curr 的角色。 這樣,我們只需要 min(m, n) 個條目即可完成計算。
在此處插入說明。
在此處插入說明。
在此處插入說明。
要使用 2*min(m, n) 個條目和 o(1) 的額外空間計算 LCS 的長度,我們可以使用滾動陣列的方法。 下面是使用 Go 語言實現的演算法:
package mainimport ( "fmt")func lcslengthrolling(x, y string) int c := make(int, 2) for i := range c for i := 1; i <= m; i++ else }return c[m%2][n]}func max(a, b int) int return b}func main()
要使用 min(m, n) 條目和 o(1) 的額外空間計算 LCS 的長度,我們可以使用一維陣列並在計算過程中覆蓋舊值。 下面是使用 Go 語言實現的演算法:
package mainimport ( "fmt")func lcslengthmin(x, y string) int c := make(int, n+1) for i := 1; i <= m; i++ else prev = temp } return c[n]}func max(a, b int) int return b}func main()
兩種實現都可以在 o(mn) 的時間複雜度內計算 LCS 的長度,但分別使用 o(min(m, n)) 和 o(2*min(m, n)) 的空間複雜度。
在此處插入說明。
在此處插入說明。
在此處插入說明。