这个题解利用了一种遍历和记录策略,使用了栈来记录负数的索引位置。首先,代码在数组末尾添加了一个0作为哨兵值,以便处理到达数组末尾的情况。接着,通过遍历数组,记录每个非零元素的长度,同时记录遇到的负数的位置。当遇到0或者到达数组末尾时,根据栈中负数的数量决定如何计算最长的乘积为正的子数组长度。如果负数数量为偶数,整个区间乘积为正,直接更新最长长度。如果为奇数,则需要去掉一个负数,以确保子数组乘积为正,通常有两种去除方式:去掉最左边或最右边的负数,这取决于哪种方式能保留更长的子数组。最后,返回记录的最大长度。
时间复杂度: O(n)
空间复杂度: O(n)
class Solution:
def getMaxLen(self, nums: List[int]) -> int:
nums.append(0) # 添加哨兵元素以简化边界处理
n = len(nums)
stack = [] # 用来存储负数的索引
length = 0 # 当前遍历的非零子数组的长度
pre = -1 # 上一个0的位置
ans = 0 # 结果变量,存储最长子数组的长度
for i in range(n):
if nums[i] == 0:
if length:
last = i
k = len(stack)
if k % 2 == 0:
ans = max(ans, length) # 如果负数个数为偶数,直接更新结果
else:
length -= min(stack[0] - pre, last - stack[-1]) # 去掉一个最不利的负数
ans = max(ans, length)
pre = i # 更新上一个0的位置
stack = [] # 清空栈
length = 0 # 重置当前长度
else:
length += 1 # 增加当前子数组的长度
if nums[i] < 0:
stack.append(i) # 记录负数的位置
return ans # 返回结果