📌  相关文章
📜  具有正积的最长子阵列的长度(1)

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

主题:具有正积的最长子阵列的长度
简介

给定一个整数数组,我们可以通过取连续的数字子序列,计算它们的乘积。例如,给定数组 [2, 3, -2, 4],可以取子序列 [2, 3],取乘积得到 6,或取子序列 [2, 3, -2, 4] 取乘积得到 -48,取子序列 [4] 取乘积得到 4。 本题要求求解最长的具有正积的连续子序列的长度。

解法

我们可以使用动态规划来解决这个问题。对于位置i,我们可以考虑模仿最长子序列的做法,维护两个变量:

  • $f_i$ 表示以位置i结尾的具有正积的最长子序列长度
  • $g_i$ 表示以位置i结尾的最长子序列长度

这样我们可以在遍历数组时递推得到$f_i$和$g_i$,最终答案即为$max_{1<=i<=n}[f_i]$。

  • 当nums[i]为0时,因为0不能作为乘积的因子,所以$f_i$和$g_i$都应该为0。
  • 当nums[i]为正数时,那么以位置i结尾的最长子序列中,我们可以将nums[i]加入某个长度大于0的连续子序列中,也可以只包含它自己,所以有

$f_i=(f_{i-1}+1)\times sign(nums[i])$

$g_i=(g_{i-1}+1)\times sign(nums[i])$

其中$sign$表示取数的符号,如果为正数返回1,如果为负数返回-1,如果为0返回0.

  • 当nums[i]为负数时,那么它是不应该被加入到以位置i结尾的最长子序列中的,此时应该考虑能不能在nums[i]和之前的最长子序列中拼凑出一个新的乘积为正数的 最长 子序列。所以有

$f_i=(g_{i-1}+1)\times sign(nums[i])$

$g_i=(f_{i-1}+1)\times sign(nums[i])$

具体实现代码如下:

class Solution:
    def getMaxLen(self, nums: List[int]) -> int:
        n = len(nums)
        if n == 0:
            return 0
        f, g = 0, 0
        res = 0
        for num in nums:
            if num > 0:
                f += 1
                g = g + 1 if g else 0
            elif num < 0:
                f, g = g + 1 if g else 0, f + 1
            else:
                f, g = 0, 0
            res = max(res, f)
        return res
时间复杂度

对于一个长度为n的数组,我们需要对其进行一次遍历,所以时间复杂度为O(n)。

空间复杂度

我们只需要使用常数个变量来存储f和g,所以空间复杂度为O(1)。

相关问题