Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.thealgorithms.dynamicprogramming;

/**
* The MaximumProductSubarray class implements the algorithm to find the
* maximum product of a contiguous subarray within a given array of integers.
*
* <p>Given an array of integers (which may contain positive numbers, negative
* numbers, and zeros), this algorithm finds the contiguous subarray that has
* the largest product. The algorithm handles negative numbers efficiently by
* tracking both maximum and minimum products, since a negative number can turn
* a minimum product into a maximum product.</p>
*
* <p>This implementation uses a dynamic programming approach that runs in O(n)
* time complexity and O(1) space complexity, making it highly efficient for
* large arrays.</p>
*/
public final class MaximumProductSubarray {

private MaximumProductSubarray() {
// Prevent instantiation
}

/**
* Finds the maximum product of any contiguous subarray in the given array.
*
* @param nums an array of integers which may contain positive, negative,
* and zero values.
* @return the maximum product of a contiguous subarray. Returns 0 if the
* array is null or empty.
*/
public static int maxProduct(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}

long maxProduct = nums[0];
long currentMax = nums[0];
long currentMin = nums[0];

for (int i = 1; i < nums.length; i++) {
// Swap currentMax and currentMin if current number is negative
if (nums[i] < 0) {
long temp = currentMax;
currentMax = currentMin;
currentMin = temp;
}

// Update currentMax and currentMin
currentMax = Math.max(nums[i], currentMax * nums[i]);
currentMin = Math.min(nums[i], currentMin * nums[i]);

// Update global max product
maxProduct = Math.max(maxProduct, currentMax);
}

return (int) maxProduct;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package com.thealgorithms.dynamicprogramming;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class MaximumProductSubarrayTest {

/**
* Test case for an array with all positive numbers.
* The expected maximum product is the product of all elements.
*/
@Test
void testAllPositiveNumbers() {
int[] nums = {2, 3, 4};
int expected = 24;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 24.");
}

/**
* Test case for an array with positive and negative numbers.
* The expected maximum product is 24 (subarray [2, -3, -4]).
*/
@Test
void testMixedPositiveAndNegative() {
int[] nums = {2, -3, -4, 1};
int expected = 24;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 24.");
}

/**
* Test case for an array containing zeros.
* The expected maximum product is 24 (subarray [4, 6]).
*/
@Test
void testArrayWithZeros() {
int[] nums = {2, 3, 0, 4, 6};
int expected = 24;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 24.");
}

/**
* Test case for an array with a single element.
* The expected maximum product is the element itself.
*/
@Test
void testSingleElement() {
int[] nums = {5};
int expected = 5;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 5.");
}

/**
* Test case for an array with all negative numbers.
* The expected maximum product is 12 (subarray [-3, -4]).
*/
@Test
void testAllNegativeNumbers() {
int[] nums = {-2, -3, -4};
int expected = 12;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 12.");
}

/**
* Test case for an array with negative numbers where odd count of negatives
* breaks the chain. The expected maximum product is 60 (subarray [-2, -3, 10]).
*/
@Test
void testOddNegativeNumbers() {
int[] nums = {-2, -3, 10, -1};
int expected = 60;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 60.");
}

/**
* Test case for an empty array.
* The expected maximum product is 0.
*/
@Test
void testEmptyArray() {
int[] nums = {};
int expected = 0;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 0 for an empty array.");
}

/**
* Test case for a null array.
* The expected maximum product is 0.
*/
@Test
void testNullArray() {
int[] nums = null;
int expected = 0;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 0 for a null array.");
}

/**
* Test case for an array with alternating positive and negative numbers.
* The expected maximum product is 6 (subarray [2, 3]).
*/
@Test
void testAlternatingNumbers() {
int[] nums = {2, 3, -2, 4};
int expected = 6;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 6.");
}

/**
* Test case for an array with large positive and negative numbers.
* The expected maximum product is 360 (subarray [6, -3, -20]).
*/
@Test
void testLargeNumbers() {
int[] nums = {6, -3, -20, 0, 5};
int expected = 360;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 360.");
}

/**
* Test case for an array with single negative number.
* The expected maximum product is the negative number itself.
*/
@Test
void testSingleNegativeElement() {
int[] nums = {-8};
int expected = -8;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be -8.");
}

/**
* Test case for an array with multiple zeros.
* The expected maximum product is 6 (subarray [2, 3]).
*/
@Test
void testMultipleZeros() {
int[] nums = {0, 2, 3, 0, 4};
int expected = 6;
int actual = MaximumProductSubarray.maxProduct(nums);
assertEquals(expected, actual, "The maximum product should be 6.");
}
}