样例:比如, 序列 [2,3,-2,4] 中乘积最大的子序列为 [2,3] ,其乘积为6。
动态规划问题,用一个数组record记录每次运算的结果。这里面有个问题,就是求前n位的乘积最大子序列的最大乘积时,的确和前n - 1位有关,但是不一定和前n - 1位的乘积最大子序列的乘积有关,他有可能是由乘积最小子序列得到的,甚至和最大最小的乘积都没有关系。
比如,看下面的子序列:
1. [2, -3, -5],前3位的乘积最大子序列为2 * -3 * -5 = 30。而前2位的乘积最大子序列为2,乘积最小子序列的值为2 * 3 = -6,可见与乘积最小的子序列是有关系的
2. [-3 , 6],前2位的乘积最大子序列与前1位没有关系,是最后一位本身。
总结一下,也就是说,前 n 位的乘积最大子序列分以下3种情况:
1. 前n - 1位的乘积最小子序列的乘积 * A[n]最大
2. 前n - 1位的乘积最大子序列的乘积 * A[n]最大
3. 前n - 1位的乘积最大子序列和乘积最小子序列的乘积 * A[n]都不是最大,而A[n]本身最大。
状态转移方程:f_max(n) = max(f_max(n - 1) * A[n], f_min(n - 1) * A[n], A[n]),其中,f_max(n)表示到原数组第n位时,乘积最大子序列的乘积,f_min(n)表示到原数组第n位时,乘积最小子序列的乘积
所以,方便起见,将记录计算结果的数组record的每个元素写成一个二元组,记录到此时,前面的数组的最大乘积和最小乘积子序列的乘积。record[i][0]表示最小值,record[i][1]表示最大值。
代码如下:
class Solution: # @param nums: an integer[] # @return: an integer def maxProduct(self, nums): n = len(nums) if n == 0: return None # 每一次运算记录最大值和最小值,最小值放在第一位,最大值放在第二位 record = [[0, 0] for i in range(n)] # 初始化第一个记录 record[0][0], record[0][1] = nums[0], nums[0] max_value = nums[0] # 从第二个元素开始计算 index = 1 while index < n: # 一个可能的最值(最大最小不知) t1 = record[index - 1][0] * nums[index] # 另一个可能的最值(最大最小不知) t2 = record[index - 1][1] * nums[index] # 最小值 record[index][0] = min(nums[index], t1, t2) # 最大值 record[index][1] = max(nums[index], t1, t2) # 最大值比较函数 max_value = max(record[index][1], max_value) index += 1 return max_value # write your code here