1567. 乘积为正数的最长子数组长度 - 力扣(LeetCode)
题目描述
给你一个整数数组 nums ,请你求出乘积为正数的最长子数组的长度。 子数组是数组中连续的一段元素。
解法

状态定义
fx[i]:以nums[i]结尾,乘积为正数的最长子数组长度gx[i]:以nums[i]结尾,乘积为负数的最长子数组长度
重点:必须强制「以 i 结尾」,连续子数组 DP 经典套路;遇到 0 直接清零,0 会把乘积打断,正负都不存在。
状态转移逻辑
- numsi > 0
- 当前是正数:正数 × 正乘积 → 还是正。
fx[i] = fx[i-1]+1;如果前面没有正的,就只能取自己长度 1。 - 正数 × 负乘积 → 还是负。前面不存在负子数组 (gx i-1=0),则
gx[i]=0;否则gx[i] = gx[i-1]+1
- 当前是正数:正数 × 正乘积 → 还是正。
- numsi < 0
- 负数会翻转正负!负数 × 前面负乘积 → 变成正数。所以
fx[i]继承上一轮 gx:gx[i-1]==0则 0,否则gx[i-1]+1 - 负数 × 前面正乘积 → 变成负数,
gx[i] = fx[i-1]+1
- 负数会翻转正负!负数 × 前面负乘积 → 变成正数。所以
- numsi == 0 乘积直接为 0,既不是正数也不是负数,
fx[i]=0,gx[i]=0
cpp
class Solution {
public:
int getMaxLen(vector<int>& nums) {
int n = nums.size();
vector<int> fx(n, 0);
vector<int> gx(n, 0);
fx[0] = nums[0] > 0 ? 1 : 0;
gx[0] = nums[0] < 0 ? 1 : 0;
int ret = fx[0];
for (int i = 1; i < n; i++) {
if (nums[i] > 0) {
fx[i] = max(1, fx[i - 1] + 1);
gx[i] = gx[i-1]==0?0:gx[i - 1] + 1;
} else {
fx[i] = gx[i-1]==0?0:gx[i - 1] + 1;
gx[i] = fx[i - 1] + 1;
}
if (nums[i] == 0) {
gx[i] = 0, fx[i] = 0;
}
ret = ret > fx[i] ? ret : fx[i];
}
return ret;
}
};