LeetCode 152. Maximum Product Subarray 求最大子数组乘积

353 阅读2分钟

leetcode.com/problems/ma…

Discuss:www.cnblogs.com/grandyang/p…

Given an integer array nums, find a contiguous non-empty subarray within the array that has the largest product, and return the product.

It is guaranteed that the answer will fit in a 32-bit integer.

subarray is a contiguous subsequence of the array.

 

Example 1:

Input: nums = [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.

Example 2:

Input: nums = [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.

 

Constraints:

  • 1 <= nums.length <= 2 * 104
  • -10 <= nums[i] <= 10
  • The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

解法一:

使用动态规划求解。要用到一个二维 dp 数组,其中 dp[i][0] 表示子数组 [0, i] 范围内并且一定包含 nums[i] 数字的最大子数组乘积,dp[i][1] 表示子数组 [0, i] 范围内并且一定包含 nums[i] 数字的最小子数组乘积,初始化时 dp[i][0] 和 dp[i][1] 都初始化为 nums[0]。那么从数组的第二个数字开始遍历,此时的最大值和最小值只会在这三个数字之间产生,即 dp[i-1][0]*nums[i],dp[i-1][1]*nums[i],和 nums[i]。所以用三者中的最大值来更新 dp[i][0],用最小值来更新 dp[i][1],然后用 dp[i][0] 来更新结果 res 即可,由于最终的结果不一定会包括 nums[n-1] 这个数字,所以 dp[n-1][0] 不一定是最终解,不断更新的结果 res 才是。我们还可以做空间优化,不需要记录每一个 nums[i] 对应的最大乘积和最小乘积,只需要记录前一个的最大乘积和最小乘积即可,参见代码如下:

class Solution {
    fun maxProduct(nums: IntArray): Int {

        val numbersSize = nums.size
        val dp = Array(size = 2, init = { IntArray(size = 2, init = { nums[0] }) })
        var result = nums[0]

        for (i in 1 until nums.size) {
            val x = i % 2
            val y = (i - 1) % 2
            dp[x][0] = getMaxFromThreeNumer(dp[y][0] * nums[i], dp[y][1] * nums[i], nums[i])
            dp[x][1] = getMinFromThreeNumer(dp[y][0] * nums[i], dp[y][1] * nums[i], nums[i])
            result = Math.max(dp[x][0], result)
        }

        return result
    }

    private fun getMaxFromThreeNumer(a: Int, b: Int, c: Int): Int {
        var max = Math.max(a, b)
        max = Math.max(max, c)
        return max
    }

    private fun getMinFromThreeNumer(a: Int, b: Int, c: Int): Int {
        var min = Math.min(a, b)
        min = Math.min(min, c)
        return min
    }
}