一、题意
给出一个整数数组 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. 乘积为正数的最长子数组长度官方解法