📜  门| GATE-CS-2004 |第 48 题(1)

📅  最后修改于: 2023-12-03 15:42:15.582000             🧑  作者: Mango

介绍

这是一道来自 GATE-CS-2004 的面试题,需要求解一个数值的最大子序列乘积问题。给出序列 $a_1, a_2, ..., a_n$,求它的子序列中所有元素的乘积最大值。本题目需要你提供一个时间复杂度为 $O(n)$ 的解法。

解题思路

这道题的解法非常巧妙,需要运用到动态规划的思想。我们定义两个 DP 数组,分别为 $p_i$ 和 $n_i$。其中,$p_i$ 表示以 $a_i$ 为结尾的数值最大子序列乘积,$n_i$ 表示以 $a_i$ 为结尾的数值最小子序列乘积。初始化时,$p_1 = a_1, n_1 = a_1$。对于 $i > 1$,我们根据 $a_i$ 的正负性分别计算:

  • 若 $a_i > 0$,则 $p_i = \max {a_i, a_ip_{i-1}}$,因为要求最大值,所以我们只需要判断 $a_i$ 和 $a_ip_{i-1}$ 哪个更大;
  • 若 $a_i < 0$,则 $p_i = \max {a_i, a_in_{i-1}}$。这样的原因与上面类似,因为要求最大值,所以我们只需要判断 $a_i$ 和 $a_in_{i-1}$ 哪个更大。同时,我们还需要计算 $n_i$,这时有 $n_i = \min {a_i, a_ip_{i-1}}$。

最终答案即为 $\max{p_i}$。

代码实现

以下是 Python 代码的实现:

def max_product_subarray(nums: List[int]) -> int:
    n = len(nums)
    p_max, n_min = [0] * n, [0] * n
    p_max[0], n_min[0], res = nums[0], nums[0], nums[0]
    for i in range(1, n):
        if nums[i] > 0:
            p_max[i] = max(nums[i], nums[i] * p_max[i-1])
            n_min[i] = min(nums[i], nums[i] * n_min[i-1])
        else:
            p_max[i] = max(nums[i], nums[i] * n_min[i-1])
            n_min[i] = min(nums[i], nums[i] * p_max[i-1])
        res = max(res, p_max[i])
    return res