LeetCode - 乘积为正数的最长子数组长度

245 阅读2分钟
题目

leetcode.cn/problems/ma…

题目描述

给你一个整数数组 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] 。

解决方案
  • 解决思路:通过已知求未知
  • 以第0个元素为结尾的,乘积为正数的最长连续子数组的长度,我们是知道的,如果是元素为正数,那么长度就是1,如果元素为符合,那么长度就为0,所有得有一个数组zheng[]做记录;
  • 遍历数组,当元素为正数,则zheng[i]为zheng[i-1]+1;当元素为负数,需要特殊处理,因为负负得正的关系,所有zheng[i]的值取决于以第i-1个元素为结尾的,乘积为负数的最长连续子数组的长度,所以得有一个数组fu[]做记录,记录以第i个元素为结尾的,乘积为负数的最长连续子数组的长度;
  • 循环一次,找出zheng[]数组的最大值,就是最终结果。
public int getMaxLen(int[] nums) {
    if (nums == null || nums.length == 0) return -1;

    /***
     * 记录以第i元素为结尾,乘积为正数的最长连续子数组的长度,注意只考虑长度,不考虑大小值
     * 以[1,-2,-3,4]为例子,zheng[0]=1 zheng[1]=0
     */
    int[] zheng = new int[nums.length];
    /***
     * 记录以第i元素为结尾,乘积为负数的最长连续子数组的长度,注意只考虑长度,不考虑大小值
     * 以[1,-2,-3,4]为例子,fu[0]=0 fu[1]=2 fu[2]=1
     * 这个数组主要起辅助作用,当nums[i]为负数,如果fu[i-1]>0,则zheng[i] = fu[i-1]+1,因为负负得正
     */
    int[] fu = new int[nums.length];
    int maxLength = 0;
    if (nums[0] > 0) {
        zheng[0] = 1;//以第0个元素为结尾,乘积为正数的最长连续子数组的长度为1
    } else if (nums[0] < 0) {
        fu[0] = 1;//以第0个元素为结尾,乘积为负数的最长连续子数组的长度为1
    }

    for (int i = 1; i < nums.length; i++) {//遍历数组
        if (nums[i] > 0) {//当前元素是正数
            zheng[i] = zheng[i - 1] + 1;//加1
        } else if (nums[i] < 0) {//当前元素是负数
            zheng[i] = fu[i - 1] > 0 ? fu[i - 1] + 1 : 0;//因为负负得正,所以zheng数组的值取决于fu数组
            fu[i] = zheng[i - 1] + 1;//因而fu数组的取值取决于正数组
        } else {//当前元素是0
            zheng[i] = fu[i] = 1;
        }

        maxLength = Math.max(maxLength, zheng[i]);//找出这轮循环的最大值
    }
    return maxLength;
}