Skip to content

Commit e22ce00

Browse files
authored
feat-Add MaximumProductSubarray (TheAlgorithms#6711)
* feat-Add MaximumProductSubarray * feat-changes * fix: correct MaximumProductSubarray compilation errors * fix-lints * fix: apply clang-format to MaximumProductSubarrayTest.java * fix: prevent integer overflow in MaximumProductSubarray using long type
1 parent 4fe37c3 commit e22ce00

File tree

2 files changed

+210
-0
lines changed

2 files changed

+210
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.thealgorithms.dynamicprogramming;
2+
3+
/**
4+
* The MaximumProductSubarray class implements the algorithm to find the
5+
* maximum product of a contiguous subarray within a given array of integers.
6+
*
7+
* <p>Given an array of integers (which may contain positive numbers, negative
8+
* numbers, and zeros), this algorithm finds the contiguous subarray that has
9+
* the largest product. The algorithm handles negative numbers efficiently by
10+
* tracking both maximum and minimum products, since a negative number can turn
11+
* a minimum product into a maximum product.</p>
12+
*
13+
* <p>This implementation uses a dynamic programming approach that runs in O(n)
14+
* time complexity and O(1) space complexity, making it highly efficient for
15+
* large arrays.</p>
16+
*/
17+
public final class MaximumProductSubarray {
18+
19+
private MaximumProductSubarray() {
20+
// Prevent instantiation
21+
}
22+
23+
/**
24+
* Finds the maximum product of any contiguous subarray in the given array.
25+
*
26+
* @param nums an array of integers which may contain positive, negative,
27+
* and zero values.
28+
* @return the maximum product of a contiguous subarray. Returns 0 if the
29+
* array is null or empty.
30+
*/
31+
public static int maxProduct(int[] nums) {
32+
if (nums == null || nums.length == 0) {
33+
return 0;
34+
}
35+
36+
long maxProduct = nums[0];
37+
long currentMax = nums[0];
38+
long currentMin = nums[0];
39+
40+
for (int i = 1; i < nums.length; i++) {
41+
// Swap currentMax and currentMin if current number is negative
42+
if (nums[i] < 0) {
43+
long temp = currentMax;
44+
currentMax = currentMin;
45+
currentMin = temp;
46+
}
47+
48+
// Update currentMax and currentMin
49+
currentMax = Math.max(nums[i], currentMax * nums[i]);
50+
currentMin = Math.min(nums[i], currentMin * nums[i]);
51+
52+
// Update global max product
53+
maxProduct = Math.max(maxProduct, currentMax);
54+
}
55+
56+
return (int) maxProduct;
57+
}
58+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package com.thealgorithms.dynamicprogramming;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
class MaximumProductSubarrayTest {
8+
9+
/**
10+
* Test case for an array with all positive numbers.
11+
* The expected maximum product is the product of all elements.
12+
*/
13+
@Test
14+
void testAllPositiveNumbers() {
15+
int[] nums = {2, 3, 4};
16+
int expected = 24;
17+
int actual = MaximumProductSubarray.maxProduct(nums);
18+
assertEquals(expected, actual, "The maximum product should be 24.");
19+
}
20+
21+
/**
22+
* Test case for an array with positive and negative numbers.
23+
* The expected maximum product is 24 (subarray [2, -3, -4]).
24+
*/
25+
@Test
26+
void testMixedPositiveAndNegative() {
27+
int[] nums = {2, -3, -4, 1};
28+
int expected = 24;
29+
int actual = MaximumProductSubarray.maxProduct(nums);
30+
assertEquals(expected, actual, "The maximum product should be 24.");
31+
}
32+
33+
/**
34+
* Test case for an array containing zeros.
35+
* The expected maximum product is 24 (subarray [4, 6]).
36+
*/
37+
@Test
38+
void testArrayWithZeros() {
39+
int[] nums = {2, 3, 0, 4, 6};
40+
int expected = 24;
41+
int actual = MaximumProductSubarray.maxProduct(nums);
42+
assertEquals(expected, actual, "The maximum product should be 24.");
43+
}
44+
45+
/**
46+
* Test case for an array with a single element.
47+
* The expected maximum product is the element itself.
48+
*/
49+
@Test
50+
void testSingleElement() {
51+
int[] nums = {5};
52+
int expected = 5;
53+
int actual = MaximumProductSubarray.maxProduct(nums);
54+
assertEquals(expected, actual, "The maximum product should be 5.");
55+
}
56+
57+
/**
58+
* Test case for an array with all negative numbers.
59+
* The expected maximum product is 12 (subarray [-3, -4]).
60+
*/
61+
@Test
62+
void testAllNegativeNumbers() {
63+
int[] nums = {-2, -3, -4};
64+
int expected = 12;
65+
int actual = MaximumProductSubarray.maxProduct(nums);
66+
assertEquals(expected, actual, "The maximum product should be 12.");
67+
}
68+
69+
/**
70+
* Test case for an array with negative numbers where odd count of negatives
71+
* breaks the chain. The expected maximum product is 60 (subarray [-2, -3, 10]).
72+
*/
73+
@Test
74+
void testOddNegativeNumbers() {
75+
int[] nums = {-2, -3, 10, -1};
76+
int expected = 60;
77+
int actual = MaximumProductSubarray.maxProduct(nums);
78+
assertEquals(expected, actual, "The maximum product should be 60.");
79+
}
80+
81+
/**
82+
* Test case for an empty array.
83+
* The expected maximum product is 0.
84+
*/
85+
@Test
86+
void testEmptyArray() {
87+
int[] nums = {};
88+
int expected = 0;
89+
int actual = MaximumProductSubarray.maxProduct(nums);
90+
assertEquals(expected, actual, "The maximum product should be 0 for an empty array.");
91+
}
92+
93+
/**
94+
* Test case for a null array.
95+
* The expected maximum product is 0.
96+
*/
97+
@Test
98+
void testNullArray() {
99+
int[] nums = null;
100+
int expected = 0;
101+
int actual = MaximumProductSubarray.maxProduct(nums);
102+
assertEquals(expected, actual, "The maximum product should be 0 for a null array.");
103+
}
104+
105+
/**
106+
* Test case for an array with alternating positive and negative numbers.
107+
* The expected maximum product is 6 (subarray [2, 3]).
108+
*/
109+
@Test
110+
void testAlternatingNumbers() {
111+
int[] nums = {2, 3, -2, 4};
112+
int expected = 6;
113+
int actual = MaximumProductSubarray.maxProduct(nums);
114+
assertEquals(expected, actual, "The maximum product should be 6.");
115+
}
116+
117+
/**
118+
* Test case for an array with large positive and negative numbers.
119+
* The expected maximum product is 360 (subarray [6, -3, -20]).
120+
*/
121+
@Test
122+
void testLargeNumbers() {
123+
int[] nums = {6, -3, -20, 0, 5};
124+
int expected = 360;
125+
int actual = MaximumProductSubarray.maxProduct(nums);
126+
assertEquals(expected, actual, "The maximum product should be 360.");
127+
}
128+
129+
/**
130+
* Test case for an array with single negative number.
131+
* The expected maximum product is the negative number itself.
132+
*/
133+
@Test
134+
void testSingleNegativeElement() {
135+
int[] nums = {-8};
136+
int expected = -8;
137+
int actual = MaximumProductSubarray.maxProduct(nums);
138+
assertEquals(expected, actual, "The maximum product should be -8.");
139+
}
140+
141+
/**
142+
* Test case for an array with multiple zeros.
143+
* The expected maximum product is 6 (subarray [2, 3]).
144+
*/
145+
@Test
146+
void testMultipleZeros() {
147+
int[] nums = {0, 2, 3, 0, 4};
148+
int expected = 6;
149+
int actual = MaximumProductSubarray.maxProduct(nums);
150+
assertEquals(expected, actual, "The maximum product should be 6.");
151+
}
152+
}

0 commit comments

Comments
 (0)