乘积最大子数组——动态规划

78 阅读1分钟

image.png

步骤

  1. ans维护目前的最大值,ma当前节点所在的子序列的目前的最大值,mi则是当前节点所在的子序列的目前的最小值,
  2. 所谓目前的最小值也就是不考虑当前节点之后的数字,因为遍历还没完成
  3. 为什么只考虑当前节点的子序列,而不记录之前的子序列,因为ans已经维护了目前为止所有子序列的最大值,也就是说能比ans更大的只有现在依旧具有变大可能的当前节点子序列(因为子序列是连续的,只有当前节点的这个可以继续扩展)
  4. 维护mi则是因为如果下一个值是负数,那么最大值就变成了最小值,最小值变成了最大值
  5. 所以for循环中ma要记录的是max(ma1 * v, v, mi1 * v))三者的最大值,从而由记录上一个节点子序列的目前的最大值变为记录当前节点所在的子序列的目前的最大值,
  6. mi同理
  7. 最后再让更新后的ma与ans比较,维护一下目前的最大值
  8. 至于ma1,mi1,因为我们更新时,需要之前的值,
func maxProduct(nums []int) int {
	ans,ma,mi := nums[0],nums[0],nums[0]
    for i,v := range nums {
        if i == 0 {
            continue
        }
        ma1,mi1 := ma,mi
        ma = max(ma1 * v, max(v, mi1 * v))
        mi = min(mi1 * v, min(v, ma1 * v))
        ans = max(ans, ma)
    }
    return ans
}

func max(i,j int) int {
    if i > j {
        return i 
    }
    return j
}
func min(i,j int) int {
    if i < j {
        return i 
    }
    return j
}