[動態規劃系列] —— 線性DP之LIS與LCS

最長上升子序列

給定一個無序的整數數組,找到其中最長上升子序列的長度。

例如對於[10,9,2,5,3,7,101,18]返回4。python

考慮第i位數字nums[i]是否能夠繼承以前的狀態,須要知道以前狀態子序列的長度n與最右值m。若是nums[i]大於m,狀態i的長度爲n+1,最右值爲nums[i]。數組

上述的動態規劃過程能夠用一維數組記錄中間狀態,對於status[i]記錄了以nums[i]爲子序列最後一個元素的子序列長度。status[i]的計算須要遍歷以前的全部狀態,取最大長度。code

def solution(nums):
    if not nums: return 0
    status = [1]*len(nums)
    for i in range(1, len(nums)):
        for j in range(i):
            if nums[i] > nums[j]: status[i] = max(status[i], status[j]+1)
    return max(status)

最長公共子序列

給定兩個字符串 text1text2,返回這兩個字符串的最長公共子序列的長度。

例如對於text1 = "abcde",text2 = "ace" 返回3。繼承

考慮對於中間狀態(i, j),text1[i]與text2[j]的加入是否對已有狀態產生了影響。leetcode

  1. text1[i]與text2[j]的加入對已有狀態無影響,狀態(i, j) = 狀態(i-1, j-1) 。
  2. text1[i]與text2[j-1]匹配,狀態(i, j) = 狀態(i, j-1)。
  3. text2[j]與text1[i-1]匹配,狀態(i, j) = 狀態(i-1, j)。
  4. text1[i] == text2[j],text[i]與text[j]匹配,狀態(i, j) = 狀態(i-1, j-1) + 1。

上述的動態規劃過程能夠用二維數組記錄中間狀態,對於status[i][j]記錄了text[:i]與text[:j]的最長公共子序列的長度。status[i][j]的計算依賴於status[i-1][j],status[i][j-1],status[i-1][j-1]。字符串

def solution(text1, text2):
    n, m = len(text1), len(text2)
    status = [[0]*(m+1) for _ in range(n+1)]
    for i in range(1, n+1):
        for j in range(1, m+1):
            status[i][j] = max(status[i-1][j], status[i][j-1])
            if text1[i-1] == text2[j-1]:
                status[i][j] = max(status[i][j], 1 + status[i-1][j-1])
    return status[n][m]

對於狀況1,已經包含在status[i-1][j]或status[i][j-1]中。get

相關文章
相關標籤/搜索