動態規劃法求解最長上升子串問題

問題描述: 給出一個array的數值(有正有負),給出一個最長的上升子串(可以不連續)的長度

定義子狀態: m[i]m[i]表示以數組元素A[i]A[i]結尾的最長上升子串的長度

狀態轉移關係m[j]=maxi<j,A[i]<A[j]m[i]+1m[j]=\max \limits_{i<j,A[i]<A[j]}m[i]+1

  • 示例
def MaxAscendOrder(array):
    # 僅要得到最大上升子串的長度
    m = [1 for _ in range(len(array))]     # 初始狀態值,記錄當前元素爲子串最後一個元素的最大長度
    for i in range(1, len(array)):
        max_len = m[i]
        for j in range(0, i):
            if array[i] > array[j]:
                max_len = max(max_len, m[j] + 1)
        m[i] = max_len
    return max(m)
print(MaxAscendOrder([1,2,3,4,5,6,7]))   # 7
print(MaxAscendOrder([1,3,2,4,5,3,9]))   # 5
print(MaxAscendOrder([3,2,1,2,6,4,7]))   # 4

思考:如果除了給出最大長度值,還要給出對應的子串呢?

解決方案:再構造一個狀態數組,記錄當前位置最大長度對應的子串序列

def MaxAscendOrder2(array):
    # 不僅要得到最大上升子串的長度,想要給出相應的一組子串
    m = [1 for _ in range(len(array))]     # 初始狀態值,記錄當前元素爲子串最後一個元素的最大長度
    s = [[] for _ in range(len(array))]    # 初始狀態值,記錄當前元素爲子串最後一個元素的最大長度的子串序列
    s[0] = [array[0]]
    for i in range(1, len(array)):
        max_len = m[i]
        max_len_arrary = [array[i]]
        for j in range(0, i):
            if array[i] > array[j]:
                max_len = max(max_len, m[j] + 1)
                if m[j] + 1 == max_len:
                    max_len_arrary = s[j] + [array[i]]
        m[i] = max_len
        s[i] = max_len_arrary
    return max(m), s[m.index(max(m))]
length, array = MaxAscendOrder2([1,2,3,4,5,6,7])
print(length)    # [1, 2, 3, 4, 5, 6, 7]
print(array)     # 7

length, array = MaxAscendOrder2([1,3,2,4,5,3,9])
print(length)   # [1, 2, 4, 5, 9]
print(array)    # 5

length, array = MaxAscendOrder2([3,2,1,2,6,4,7])
print(length)   # [1, 2, 4, 7]
print(array)    # 4
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章