leetcode 1567. 乘积为正数的最长子数组长度

一、题意

给出一个整数数组 nums ,求连续相乘为正数的最大值,包括单个元素的情况。

二、解法

解法一:
根据提示自己写的:
1、判断是否是0,是则根据负数的数量的奇偶,计算长度:

  • 偶数,计算当前位置到start 位置的长度
  • 奇数,计算当前位置到第一个负数后位置的长度。
    2、判断是否是负数,是:
  • 是第一个负数,计算出之前的长度
  • 不是第一个负数,判断奇偶:
    1、奇数,计算出该负数之前的位置到start位置的长度,计算出第一个负数后位置到当前位置的长度,与最大值比较大小。
    2、偶数,如果是最后一个元素,则计算出到start的长度。
    时间复杂度: O ( n ) O(n) O(n)
    空间复杂度: O ( 1 ) O(1) O(1)

解法二(动态规划):
用positive记录到当前位置乘积为正数的最长数组长度,用negative计算出到当前位置乘积为负数的最长数组长度。
1、当前为正数, 不会改变乘积的符号:
p o s i t i v e = p o s i t i v e + 1 positive=positive+1 positive=positive+1
negative,如果没有负数则为0,不然 n e g a t i v e = n e g a t i v e + 1 negative=negative+1 negative=negative+1
2、当前为负数:
如果有负数,则 p o s i t i v e = n e g a t i v e + 1 positive=negative+1 positive=negative+1,不然为0
n e g a t i v e = p o s i t i v e + 1 negative=positive+1 negative=positive+1
3、当前为0:
$ positive =negative = 0$
每次计算后,positive都要与最大值比较大小。
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)

三、代码

1、解法一

int getMaxLen(vector<int>& nums) {
    int n=nums.size();
    int dp=1;

    int maxC=0;
        int start=0,end=0;
        int startNegative =-1;
        int ct=0;
        for(int i=0;i<nums.size();i++){
                //如果有0 数组分成两段
             if(nums[i]==0){
                    //且负数为偶数,则直接计算长度
                    if(i-1>start&&ct%2==0){
                        maxC= max(maxC,i-start);
                    }
                    else if(i-1>start&&ct%2==1){
                            //负数为奇数个 求去掉第一个负数后的长度
                            maxC= max(maxC,i-startNegative-1);
                    }
                    start = end = i+1;
                    ct=0;

             }
             else if(nums[i]<0){
                    //如果是第一个负数
                  ct++;
                    end++;
                if(ct==1){
                 startNegative = i;
                    //第一个负数 计算出负数之前的长度
                     maxC= max(maxC,i-start);
                }
                else if(ct%2==1){
                        //奇数个负数 计算出去掉第一个负数后的长度 和 去掉最后一个负数后的长度
                        maxC= max(maxC,i-startNegative-1);
                        maxC= max(maxC,i-start);
                }
                else{
                        //偶数个负数 且到末尾
                    if(i==n-1){

                        maxC= max(maxC,end-start);
                    }
                }
             }
             else{
                end++;
             }
             if(i==n-1&&nums[i]>0){
                    if(ct%2==0){
                        maxC= max(maxC,end-start);
                    }
                    else{
                        maxC= max(maxC,end-1-startNegative);
                    }
             }
        }
            return maxC;
 }

2、解法二

 int getMaxLen(vector<int>& nums) {
   
    int positive = 0;
    int negative=0;
    int maxC= 0;
    for(int i=0;i<nums.size();i++){
        if(nums[i]>0){
            positive++;
            negative = negative >0?negative+1:negative;
        }
        else if(nums[i]<0){
            int po = positive;
            positive = negative >0?negative+1:negative;
            negative =  po+1;
        }
        else{
            positive  =negative = 0;
        }
        maxC= max(maxC,positive);
    }
            return maxC;
 }

四、引用

[1] leetcode:1567. 乘积为正数的最长子数组长度
[2] leetcode:1567. 乘积为正数的最长子数组长度官方解法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值