标题: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)
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
- 遍历数组,计算乘积,分别记录
positiveNum(正数)
和negativeNum负数
的个数 - 然后每遍历一个数就记录一下正数最大长度
max
初始化:
//正数个数
int positiveNum = 0;
//负数个数
int negativeNum = 0;
//记录最大正数个数
int max = 0;
- 情况1,遇到0,正数负数都会被重置成0
for(int item: nums){
if(item == 0){
//遇到0 重置正负数计数
positiveNum = 0;
negativeNum = 0;
}
- 情况2 ,遍历到正数
- 正数+1
- 如果
负数 != 0
负数 * 正数 = 负数
if(item > 0){
//当前数是正数
//正数+1
positiveNum++;
if(negativeNum != 0){
//如果负数也有计数 负数+1 (主要用来 -- 得正,为正数服务计数)
negativeNum ++;
}
}
- 情况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;
}
- 每次遍历完,对比记录下正数最大长度
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;
}
}