1. 问题描述:
给你一个整数数组 nums ,请你求出乘积为正数的最长子数组的长度。一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。请你返回乘积为正数的最长子数组长度。
示例 1:
输入:nums = [1,-2,-3,4]
输出:4
解释:数组本身乘积就是正数,值为 24 。
示例 2:
输入:nums = [0,1,-2,-3,-4]
输出:3
解释:最长乘积为正数的子数组为 [1,-2,-3] ,乘积为 6 。
注意,我们不能把 0 也包括到子数组中,因为这样乘积为 0 ,不是正数。
示例 3:
输入:nums = [-1,-2,-3,0,1]
输出:2
解释:乘积为正数的最长子数组是 [-1,-2] 或者 [-2,-3] 。
示例 4:
输入:nums = [-1,2]
输出:1
示例 5:
输入:nums = [1,2,3,5,-6,4,0,10]
输出:4
提示:
1 <= nums.length <= 10^5
-10^9 <= nums[i] <= 10^9
2. 思路分析:
① 之前力扣中的152题是关于最大乘积子数组的乘积的题目,求解的是最大乘积子数组的乘积,这里求解的是最大乘积子数组的长度,一开始的时候没有什么思路于是看了一下力扣官方题解才理解了,思路也是类似的,这里使用两个列表来记录到以当前位置i结尾的最大乘积为正数与负数的长度,理解这两个列表的含义接下来就比较好办了,可以分为三种情况进行讨论(由上一个位置推出下一个位置的两个列表的对应的值)
② 因为需要由上一个位置推出当前位置的正数乘积长度与负数乘积长度对应的值,所以在一开始的时候需要判断出nums[0]的值,nums[0] > 0那么positive[0] = 1,nums[0] < 0那么negative[0] = 1,然后从第二个位置开始分为三种情况进行递推:
(1) 当nums[i] > 0 时那么当前正数乘积的长度应该在上一次正数列表的值的基础上加1,也就是positive[i] = positive[i - 1] + 1,负数列表negative[i]的值需要判断negative[i - 1]的值是否大于0,也就是negative上一个位置的值是否大于0,假如大于0我们在上一次的基础上对负数列表的值进行加1,也就是negative[i] = negative[i - 1] + 1(判断negative上一个位置是否大于0是因为有可能上一个位置是0)否则等于0
(2) 当nums[i] < 0,那么正数乘积的长度需要判断上一个负数乘积长度的列表的值是否大于0假如大于0那么等于上一个位置的负数乘积的长度的值加1,否则等于0(这里也是可能上一个位置出现0的情况),对于负数乘积的长度应该是等于上一次正数乘积的长度上加1即可
(3) 当nums[i] == 0时那么两个列表的值都等于0
3. 代码如下:
from typing import List
class Solution:
def getMaxLen(self, nums: List[int]) -> int:
n = len(nums)
negative, positive = [0] * n, [0] * n
if nums[0] > 0: positive[0] = 1
if nums[0] < 0: negative[0] = 1
maxLength = positive[0]
for i in range(1, n):
if nums[i] > 0:
positive[i] = positive[i - 1] + 1
negative[i] = negative[i - 1] + 1 if negative[i - 1] > 0 else 0
elif nums[i] < 0:
positive[i] = negative[i - 1] + 1 if negative[i - 1] > 0 else 0
negative[i] = positive[i - 1] + 1
else:
positive[i] = negative[i] = 0
maxLength = max(maxLength, positive[i])
return maxLength