算法日常・每日刷题--<动态规划>22

1567. 乘积为正数的最长子数组长度 - 力扣(LeetCode)

题目描述

给你一个整数数组 nums ,请你求出乘积为正数的最长子数组的长度。 子数组是数组中连续的一段元素。

解法

状态定义

  • fx[i]:以 nums[i] 结尾,乘积为正数的最长子数组长度
  • gx[i]:以 nums[i] 结尾,乘积为负数的最长子数组长度

重点:必须强制「以 i 结尾」,连续子数组 DP 经典套路;遇到 0 直接清零,0 会把乘积打断,正负都不存在。

状态转移逻辑

  1. numsi > 0
    • 当前是正数:正数 × 正乘积 → 还是正。fx[i] = fx[i-1]+1;如果前面没有正的,就只能取自己长度 1。
    • 正数 × 负乘积 → 还是负。前面不存在负子数组 (gx i-1=0),则gx[i]=0;否则gx[i] = gx[i-1]+1
  2. numsi < 0
    • 负数会翻转正负!负数 × 前面负乘积 → 变成正数。所以fx[i]继承上一轮 gx:gx[i-1]==0则 0,否则gx[i-1]+1
    • 负数 × 前面正乘积 → 变成负数,gx[i] = fx[i-1]+1
  3. 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;
    }
};
相关推荐
CC数分13 分钟前
统计学基础|先把问题问对:数据分析的六大类型
大数据·人工智能·算法
地平线开发者1 小时前
CLIP 的训练机制:从对比学习到图文对齐
深度学习·算法·自动驾驶
hetao17338371 小时前
2026-11-02 hetao1733837 的刷题记录
c++·算法
Geektec1 小时前
IMU 选型完全指南:从硬件参数到算法融合的系统工程视角
算法·imu·陀螺仪·加速度计·元器件选型
CQU_JIAKE1 小时前
11.2【A】
算法
Godspeed Zhao2 小时前
从零开始学AI21——决策树
算法·决策树·机器学习
开开心心就好2 小时前
网页图片批量下载工具,输入链接就保存
服务器·算法·leetcode·支持向量机·pdf·ocr·1024程序员节
Navigator_Z3 小时前
LeetCode //C - 1313. Decompress Run-Length Encoded List
c语言·算法·leetcode
dialect_4 小时前
CODEFORCES ROUND 1127 DIV2
开发语言·c++·算法
Nuanyt4 小时前
LeetCode Hot 100 链表专题(四)· 3 题(Java)
java·算法·leetcode·链表·双指针