Problem#
Given an array of integers nums
, find the maximum length of a subarray where the product of all its elements is positive.
A subarray of an array is a consecutive sequence of zero or more values taken out of that array.
Return the maximum length of a subarray with positive product .
Examples#
Example 1#
1
2
3
Input: nums = [ 1 ,- 2 ,- 3 , 4 ]
Output: 4
Explanation: The array nums already has a positive product of 24.
Example 2#
1
2
3
4
Input: nums = [ 0 , 1 ,- 2 ,- 3 ,- 4 ]
Output: 3
Explanation: The longest subarray with positive product is [ 1 ,- 2 ,- 3 ] which has a product of 6.
Notice that we cannot include 0 in the subarray since that' ll make the product 0 which is not positive.
Example 3#
1
2
3
Input: nums = [- 1 ,- 2 ,- 3 , 0 , 1 ]
Output: 2
Explanation: The longest subarray with positive product is [- 1 ,- 2 ] or [- 2 ,- 3 ].
Constraints#
1 <= nums.length <= 10^5
-109 <= nums[i] <= 10^9
Solution#
Method 1 – Dynamic Programming (Sign Tracking)#
Intuition#
To find the maximum length of a subarray with a positive product, we can track for each position the length of the longest subarray ending there with a positive or negative product. When we see a zero, we reset. When we see a negative, the roles of positive and negative lengths swap.
Approach#
Initialize two variables: pos (length of subarray ending at current index with positive product), neg (with negative product), both set to 0.
Iterate through nums:
If nums[i] == 0: reset pos and neg to 0.
If nums[i] > 0: pos += 1, neg = neg > 0 ? neg + 1 : 0.
If nums[i] < 0: swap pos and neg, then pos = neg > 0 ? neg + 1 : 0, neg = old_pos > 0 ? old_pos + 1 : 1.
Track the maximum value of pos during the iteration.
Return the maximum value found.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public :
int getMaxLen(vector< int >& nums) {
int pos = 0 , neg = 0 , ans = 0 ;
for (int x : nums) {
if (x == 0 ) pos = neg = 0 ;
else if (x > 0 ) {
pos += 1 ;
neg = neg > 0 ? neg + 1 : 0 ;
} else {
int tmp = pos;
pos = neg > 0 ? neg + 1 : 0 ;
neg = tmp > 0 ? tmp + 1 : 1 ;
}
ans = max(ans, pos);
}
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
func getMaxLen (nums []int ) int {
pos , neg , ans := 0 , 0 , 0
for _ , x := range nums {
if x == 0 {
pos , neg = 0 , 0
} else if x > 0 {
pos ++
if neg > 0 {
neg ++
} else {
neg = 0
}
} else {
tmp := pos
if neg > 0 {
pos = neg + 1
} else {
pos = 0
}
if tmp > 0 {
neg = tmp + 1
} else {
neg = 1
}
}
if pos > ans {
ans = pos
}
}
return ans
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int getMaxLen (int [] nums) {
int pos = 0, neg = 0, ans = 0;
for (int x : nums) {
if (x == 0) pos = neg = 0;
else if (x > 0) {
pos++ ;
neg = neg > 0 ? neg + 1 : 0;
} else {
int tmp = pos;
pos = neg > 0 ? neg + 1 : 0;
neg = tmp > 0 ? tmp + 1 : 1;
}
ans = Math.max (ans, pos);
}
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
fun getMaxLen (nums: IntArray): Int {
var pos = 0
var neg = 0
var ans = 0
for (x in nums) {
if (x == 0 ) {
pos = 0 ; neg = 0
} else if (x > 0 ) {
pos++
neg = if (neg > 0 ) neg + 1 else 0
} else {
val tmp = pos
pos = if (neg > 0 ) neg + 1 else 0
neg = if (tmp > 0 ) tmp + 1 else 1
}
ans = maxOf(ans, pos)
}
return ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution :
def getMaxLen (self, nums: list[int]) -> int:
pos = neg = ans = 0
for x in nums:
if x == 0 :
pos = neg = 0
elif x > 0 :
pos += 1
neg = neg + 1 if neg > 0 else 0
else :
tmp = pos
pos = neg + 1 if neg > 0 else 0
neg = tmp + 1 if tmp > 0 else 1
ans = max(ans, pos)
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
impl Solution {
pub fn get_max_len (nums: Vec< i32 > ) -> i32 {
let (mut pos, mut neg, mut ans) = (0 , 0 , 0 );
for & x in & nums {
if x == 0 {
pos = 0 ; neg = 0 ;
} else if x > 0 {
pos += 1 ;
neg = if neg > 0 { neg + 1 } else { 0 };
} else {
let tmp = pos;
pos = if neg > 0 { neg + 1 } else { 0 };
neg = if tmp > 0 { tmp + 1 } else { 1 };
}
ans = ans.max(pos);
}
ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
getMaxLen (nums : number []): number {
let pos = 0 , neg = 0 , ans = 0 ;
for (const x of nums ) {
if (x === 0 ) pos = neg = 0 ;
else if (x > 0 ) {
pos ++ ;
neg = neg > 0 ? neg + 1 : 0 ;
} else {
const tmp = pos ;
pos = neg > 0 ? neg + 1 : 0 ;
neg = tmp > 0 ? tmp + 1 : 1 ;
}
ans = Math.max (ans , pos );
}
return ans ;
}
}
Complexity#
⏰ Time complexity: O(n)
, since we process each element once.
🧺 Space complexity: O(1)
, only a few variables are used.