算法日常・每日刷题--<动态规划>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;
    }
};
相关推荐
释厄6231 小时前
字画同体论——字即画·几何即字·漫画与小说=文本层
人工智能·算法
沫璃染墨1 小时前
从零入门数据结构与算法(一):复杂度分析——从算法效率到时间与空间复杂度
c语言·开发语言·数据结构·笔记·算法·飞书
熊猫钓鱼>_>2 小时前
面试出现 606 次的第 K 大,被拆成三个问题问
算法·面试·职场和发展·校招·面经·oj·ai生成
xuxigifxfh2 小时前
牛客:BISHI2 【模板】栈的操作
java·开发语言·windows·算法
aqiu1111112 小时前
【C++算法打怪专栏】LeetCode 402. 移掉 K 位数字(单调栈 + 贪心)
c++·算法·leetcode
糖果豆豆3 小时前
对象是字段,还是关系?集合论和范畴论吵了三十年,答案是两个都对
算法·架构
第六种自由3 小时前
[路飞]_Leetcode 22. 括号生成
javascript·算法·leetcode
isyoungboy3 小时前
事件驱动状态机与循环扫描状态机:两种计算模型的比较研究
算法·状态机
行者全栈架构师3 小时前
【鸿蒙心迹】从手机到平板、折叠屏——多端适配自查清单与踩坑实录(HarmonyOS 7.x)
前端·算法·架构