【力扣-动态规划入门】【第 6 天】1567. 乘积为正数的最长子数组长度

该博客介绍了如何使用动态规划算法解决寻找给定整数数组中乘积为正数的最长子数组长度的问题。代码示例中展示了两种方法,一种是通过维护正数和负数的计数,另一种是使用二维数组记录状态,最终找到最大正数子数组长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标题:1567. 乘积为正数的最长子数组长度
难度:中等
天数:第6天,第2/2题

给你一个整数数组 nums ,请你求出乘积为正数的最长子数组的长度。

一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。

请你返回乘积为正数的最长子数组长度。

示例  1:

输入:nums = [1,-2,-3,4]
输出:4
解释:数组本身乘积就是正数,值为 24 。

示例 2:

输入:nums = [0,1,-2,-3,-4]
输出:3
解释:最长乘积为正数的子数组为 [1,-2,-3] ,乘积为 6 。
注意,我们不能把 0 也包括到子数组中,因为这样乘积为 0 ,不是正数。

示例 3:

输入:nums = [-1,-2,-3,0,1]
输出:2
解释:乘积为正数的最长子数组是 [-1,-2] 或者 [-2,-3] 。

示例 4:

输入:nums = [-1,2]
输出:1

示例 5:

输入:nums = [1,2,3,5,-6,4,0,10]
输出:4

提示:

  • 1 <= nums.length <= 10^5
  • -10^9 <= nums[i] <= 10^9

来源:力扣(LeetCode)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:

  1. 遍历数组,计算乘积,分别记录positiveNum(正数)negativeNum负数的个数
  2. 然后每遍历一个数就记录一下正数最大长度max

初始化:

 	//正数个数
	int positiveNum = 0;
	//负数个数
	int negativeNum = 0;
	//记录最大正数个数
	int max = 0;
  1. 情况1,遇到0,正数负数都会被重置成0
	for(int item: nums){
		if(item == 0){
		//遇到0 重置正负数计数
		positiveNum = 0;
		negativeNum = 0;        
	}
  1. 情况2 ,遍历到正数
    • 正数+1
    • 如果负数 != 0 负数 * 正数 = 负数
	if(item > 0){
		//当前数是正数
		//正数+1
		positiveNum++;
		if(negativeNum != 0){
			//如果负数也有计数 负数+1  (主要用来 -- 得正,为正数服务计数)
			negativeNum ++;
		}
	}
  1. 情况3,遍历到负数
    • 负数 != 0 负负得正 正数 = 负数+1
    • 负数==0 说明没有负数,得不到正数 正数 = 0;
    • 负数 = 正数+1
	if(item < 0){
		//当前数是负数
		int temp = positiveNum;
		if(negativeNum != 0){
			//如果负数有计数   --得正  正数 = 负数+1
			positiveNum = negativeNum + 1;
		}else{
			//如果没有负数 重置正数计数 
			positiveNum = 0; 
		}
		//负数等于 -+ 得 -   负数 = 正数+1
		negativeNum = temp + 1;
	}
  1. 每次遍历完,对比记录下正数最大长度
	max = Math.max(max,positiveNum);

完整代码

class Solution {
    //动态规划,第六天 2/2
    public int getMaxLen(int[] nums) {
        //正数个数
        int positiveNum = 0;
        //负数个数
        int negativeNum = 0;
        //记录最大正数个数
        int max = 0;
        for(int item: nums){
            if(item == 0){
                //遇到0 重置正负数计数
                positiveNum = 0;
                negativeNum = 0;
           
            }else if(item > 0){
                //当前数是正数
                //正数+1
                positiveNum++;
                if(negativeNum != 0){
                    //如果负数也有计数 负数+1  (主要用来 -- 得正,为正数服务计数)
                    negativeNum ++;
                }
            
            }else if(item < 0){
                //当前数是负数
                int temp = positiveNum;
                if(negativeNum != 0){
                    //如果负数有计数   --得正  正数 = 负数+1
                    positiveNum = negativeNum + 1;
                }else{
                    //如果没有负数 重置正数计数 
                    positiveNum = 0; 
                }
                //负数等于 -+ 得 -   负数 = 正数+1
                negativeNum = temp + 1;

            }
            max = Math.max(max,positiveNum);
        }
        return max;
    }
}

使用二维数组,更耗时,更浪费内存的写法:

  • 二维数组第二维0记录负数个数
  • 二维数组第二维1记录正数个数
  • 其他思路和上边一致
class Solution {
    //动态规划,第六天 2/2
    public int getMaxLen(int[] nums) {
        int m = nums.length;
        int[][] dp = new int[m][2];

        if(nums[0] < 0){
            dp[0][0] = 1;
        }else if(nums[0] > 0){
            dp[0][1] = 1;
        }else{
            //负数个数
            dp[0][0] = 0;
            //正数个数
            dp[0][1] = 0;
        }
       
        //记录最大正数个数
        int max = dp[0][1];

        for(int i = 1;i < m ;i++){
            int item = nums[i];

            if(item == 0){
                //遇到0 重置正负数计数
                dp[i][0] = 0;
                dp[i][1] = 0;
           
            }else if(item > 0){
                //当前数是正数

                //正数+1
                dp[i][1] = dp[i-1][1] + 1;
                
                if(dp[i-1][0] != 0){
                    //如果负数也有计数 负数+1  (主要用来 -- 得正,为正数服务计数)
                    dp[i][0] = dp[i-1][0] + 1;
                }
            
            }else if(item < 0){
                //当前数是负数
                if(dp[i-1][0] != 0){
                    //如果负数有计数   --得正  正数 = 负数+1
                    dp[i][1] = dp[i-1][0] + 1;
                }else{
                    //如果没有负数 重置正数计数 
                    dp[i][0] = 0; 
                }
                dp[i][0] = dp[i-1][1] + 1;
            }
            max = Math.max(max,dp[i][1]);
        }
        return max;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Crazy丶code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值