Problem Statement
Given an integer array arr[] and an integer k, find a subsequence of exactly k elements whose product is maximum.
Return the maximum product that can be obtained.
Example 1
Input:
arr[] = [1, 2, 0, 3]
k = 2
Output:
6
The subsequence {2, 3} gives:
2 × 3 = 6
Example 2
Input:
arr[] = [1, 2, -1, -3, -6, 4]
k = 4
Output:
144
The subsequence:
{2, -3, -6, 4}
gives:
2 × (-3) × (-6) × 4 = 144
Approach
The important difficulty in this problem is the presence of negative numbers.
When multiplying numbers, a negative value can change the result significantly.
For example:
(-5) × (-4) = 20
So two negative numbers can produce a positive product.
Also:
(-10) × (-2) = 20
Therefore, keeping only the maximum product is not enough.
We need to maintain both:
max[j] = maximum product possible using j elements
min[j] = minimum product possible using j elements
Why Do We Need min[j]?
Suppose:
min[j - 1] = -20
num = -5
Then:
(-20) × (-5) = 100
The minimum product can become the maximum product when multiplied by a negative number.
Therefore, for every subsequence size, we maintain both the maximum and minimum possible products.
Java Solution
class Solution {
public int maxProduct(int[] arr, int k) {
int n = arr.length;
long[] max = new long[k + 1];
long[] min = new long[k + 1];
boolean[] possible = new boolean[k + 1];
max[0] = 1;
min[0] = 1;
possible[0] = true;
for (int num : arr) {
for (int j = Math.min(k, n); j >= 1; j--) {
if (possible[j - 1]) {
long product1 = max[j - 1] * num;
long product2 = min[j - 1] * num;
if (!possible[j]) {
max[j] = Math.max(product1, product2);
min[j] = Math.min(product1, product2);
possible[j] = true;
} else {
max[j] = Math.max(max[j],
Math.max(product1, product2));
min[j] = Math.min(min[j],
Math.min(product1, product2));
}
}
}
}
return (int) max[k];
}
}
Step-by-Step Explanation
1. Get the Array Size
int n = arr.length;
This stores the number of elements in the array.
For example:
arr = [1, 2, -3, 4]
Then:
n = 4
2. Create the max and min Arrays
long[] max = new long[k + 1];
long[] min = new long[k + 1];
These arrays store the maximum and minimum products for different subsequence sizes.
For example, if:
k = 4
then:
max[0]
max[1]
max[2]
max[3]
max[4]
are available.
They represent:
max[1] → maximum product using 1 element
max[2] → maximum product using 2 elements
max[3] → maximum product using 3 elements
max[4] → maximum product using 4 elements
Similarly:
min[1]
min[2]
min[3]
min[4]
store the minimum products.
3. Why Use long?
long[] max
long[] min
Products can become larger than the normal int range in general versions of this problem.
Using long provides a larger range for intermediate calculations.
At the end:
return (int) max[k];
returns the required int result according to the given problem signature.
4. The possible Array
boolean[] possible = new boolean[k + 1];
This tells us whether it is possible to create a subsequence of a particular size.
Initially:
possible[0] = true;
because selecting zero elements is always possible.
All other values are initially:
false
5. Initialize the Product for Zero Elements
max[0] = 1;
min[0] = 1;
We use 1 because 1 is the multiplicative identity.
For example:
1 × 5 = 5
So when we select the first element:
max[0] * num
becomes:
1 × num = num
6. Traverse Every Array Element
for (int num : arr) {
This processes each element one by one.
For:
arr = [1, 2, -3, 4]
the loop processes:
num = 1
num = 2
num = -3
num = 4
7. Traverse j Backwards
for (int j = Math.min(k, n); j >= 1; j--) {
Here, j represents the number of elements selected.
The loop goes backwards.
This is very important because we are using one-dimensional DP arrays.

Join the conversation! Your thoughts help the community grow.