mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-12-19 07:00:35 +08:00
feat-Add MaximumProductSubarray (#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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user