1. 程式人生 > >31.動態規劃-乘積最大子序列-Leetcode 152(python)

31.動態規劃-乘積最大子序列-Leetcode 152(python)

  • 題目描述

給定一個整數陣列 nums ,找出一個序列中乘積最大的連續子序列(該序列至少包含一個數)。

  • 示例

示例 1:

輸入: [2,3,-2,4]
輸出: 6
解釋: 子陣列 [2,3] 有最大乘積 6。

示例 2:

輸入: [-2,0,-1]
輸出: 0
解釋: 結果不能為 2, 因為 [-2,-1] 不是子陣列。

  • 自己的錯誤思路

自以為抄了足夠多的動態規劃的題了,怎麼著也應該對這種思想有一點理解,沒想到還是有坑,我的想法就是用dp陣列記錄到當前元素為止的子串中,能夠得到的最大乘積,自以為考慮非常周到,因為還想到了要判斷dp[i-1]<0/=0/>0和nums[i]<0/>0/=0的情況。

但是按照我的思路來做的話,如果輸入是[-2,3,-4],輸出就是3。很顯然這樣是錯的,因為我的做法是記錄最大值,那麼dp[1]就是3,但是接下來的nums[2]是-4,是個負數,如果它和dp[1]可以取的另一個值也就是-6相乘的話,很明顯能夠得到比3大的多的乘積,也就是24,然而按我的只記錄最大乘積的做法,就會認為dp[2] = 3

  • 正確的解決思路

一個比較完整健全的解決思路(來自網友):

在第i個元素時,我們能夠取到的子序列的最大乘積可能來自:

(1)nums[i]本身

(2)nums[i-1]能夠取到的最大子序列的乘積

(3)包含nums[i-1]的最大連乘值 * nums[i] (兩個部分均為正數)

(4)包含nums[i-1]的最小連乘值 * nums[i] (兩個部分均為負數)

因此對於第i個元素,我們需要記錄的值有三個:

(1)能夠取到的子序列的最大乘積

(2)包含當前位置的最大連乘值

(3)包含當前位置的最小連乘值

  • 程式碼
class Solution(object):
    def maxProduct(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        #temp記錄整個陣列的子序列最大連乘積
        temp = nums[0]
        length = len(nums)
        
        #M陣列記錄包含當前位置的最大連乘值
        M = [0 for i in range(length)]
        #m陣列記錄包含當前位置的最小連乘值
        m = [0 for i in range(length)]
        
        for i in range(length):
            if i == 0:
                M[i] = nums[i]
                m[i] = nums[i]
            else:
                #包含當前位置的最大連乘值從:當前位置和到第i-1個元素的最大連乘值的乘積、當前元素中選出
                M[i] = max(max(M[i-1]*nums[i],m[i-1]*nums[i]),nums[i])
                m[i] = min(min(M[i-1]*nums[i],m[i-1]*nums[i]),nums[i])
                
            temp = max(temp,M[i])
            
        return temp