動態規劃法求解最大子序列和問題

問題描述:給出一個數字array(其元素值可正可負),求其連續子序列中,各元素和的最大值(不要求子序列的長度)

定義子狀態m[i]m[i]表示以數組元素A[i]A[i]結尾的最大子序列之和

狀態轉移關係m[i+1]=max{m[i]+A[i+1],A[i+1]}m[i+1]=\max\{m[i]+A[i+1], A[i+1]\},或者表示成更簡單的m[i+1]=A[i+1]ifm[i]<0elsem[i]+A[i+1]m[i+1]=A[i+1] \quad if \quad m[i]<0\quad else\quad m[i]+A[i+1]

  • 代碼示例
def MaxsumOfSub(array):
    # 只需求解最大序列和
    m = [0 for _ in range(len(array))]          # 狀態數組,記錄當前位置的最大和
    m[0] = array[0]      # 第一個元素的初值
    MaxSum = array[0]       # 記錄最大和,也可以得到狀態矩陣後,最後統一求max
    for i in range(1, len(array)):            # 從第二個元素開始
        m[i] = m[i-1] + array[i] if m[i-1]>0 else array[i]
        if m[i] > MaxSum:
            MaxSum = m[i]
    return MaxSum
print(MaxsumOfSub([1,2,3,4]))    # 10
print(MaxsumOfSub([1,-1,2,-3,4,-3]))    # 4
print(MaxsumOfSub([-2,1,-1,3,-2,5]))     # 6

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

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

def MaxsumOfSub2(array):
    # 在需求解最大序列和的同時,還需要記錄子串位置
    m = [0 for _ in range(len(array))]          # 狀態數組,記錄當前位置的最大和
    s = [(0, 0) for _ in range(len(array))]       # 狀態數組,記錄當前位置的最大和對應的索引位置
    m[0] = array[0]      # 第一個元素的初值
    MaxSum = array[0]    # 記錄最大和
    MaxIndex = (0, 0)     # 記錄最大和對應的起止索引

    for i in range(1, len(array)):            # 從第二個元素開始
        if m[i-1] > 0:
            m[i] = m[i-1] + array[i]
            s[i] = (s[i-1][0], i)
        else:
            m[i] = array[i]
            s[i] = (i, i)
        if m[i] > MaxSum:
            MaxSum = m[i]
            MaxIndex = s[i]

    return MaxSum, array[MaxIndex[0]: MaxIndex[1]+1]
result, index = MaxsumOfSub2([1,2,3,4])
print(result)     # 10
print(index)     # [1, 2, 3, 4]

result, index = MaxsumOfSub2([1,-1,2,-3,4,-3])
print(result)    # 4
print(index)     # [4]

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