Problem Summary
You are given an integer array nums.
You must choose three indices i < j < k such that the value
(nums[i] - nums[j]) * nums[k]
is maximized.
Return the maximum possible value of this expression.
Constraints
- 3 ≤ nums.length ≤ 1000
- 1 ≤ nums[i] ≤ 10⁶
- A brute force O(n³) would be too slow; O(n²) or better is needed.
Understanding the Expression
We want to maximize:
(nums[i] - nums[j]) * nums[k]
The constraints are:
- i < j < k
- nums[k] is multiplied with the difference
(nums[i] - nums[j])
Important Observations
If (nums[i] - nums[j]) is negative, multiplying with positive nums[k] reduces the answer.
So ideally we want:
- nums[i] as large as possible before j
- nums[j] as small as possible
- nums[k] as large as possible after j
This naturally suggests a middle index j that splits the triplet.
Approach (Simple English)
The expression depends on three parts, separated by j:
- Best nums[i] before j
- nums[j]
- Best nums[k] after j
We can preprocess:
leftMax[i]= maximum number in nums[0..i−1]rightMax[i]= maximum number in nums[i+1..n−1]
Then for each middle index j, compute:
value = (leftMax[j] - nums[j]) * rightMax[j]
Take the maximum over all j.
Why This Works
At each j:
- The best candidate for i is the largest element before j
- The best candidate for k is the largest element after j
This yields the maximum possible value for each fixed j.
Time complexity becomes O(n).
Steps
- Build prefix max array: leftMax
- Build suffix max array: rightMax
- Loop j from 1 to n−2
- Compute value:
(leftMax[j] - nums[j]) * rightMax[j] - Track the maximum
Java Code (Optimal O(n) Solution)
class Solution {
public long maximumTripletValue(int[] nums) {
int n = nums.length;
long maxValue = 0;
// Step 1: prefix max
int[] leftMax = new int[n];
leftMax[0] = nums[0];
for (int i = 1; i < n; i++) {
leftMax[i] = Math.max(leftMax[i - 1], nums[i - 1]);
}
// Step 2: suffix max
int[] rightMax = new int[n];
rightMax[n - 1] = nums[n - 1];
for (int i = n - 2; i >= 0; i--) {
rightMax[i] = Math.max(rightMax[i + 1], nums[i + 1]);
}
// Step 3: evaluate all possible j
for (int j = 1; j < n - 1; j++) {
long left = leftMax[j];
long mid = nums[j];
long right = rightMax[j];
long value = (left - mid) * right;
if (value > maxValue) {
maxValue = value;
}
}
return maxValue;
}
}
Dry Run
Input:
nums = [12, 6, 1, 2, 7]
Step 1: leftMax
leftMax = [12, 12, 6, 1, 2] // max before each index
Step 2: rightMax
rightMax = [7, 7, 7, 7, 7] // max after each index
Step 3: Iterate j from 1 to 3
For j = 1 (nums[j] = 6):
(12 - 6) * 7 = 6 * 7 = 42 maxValue = 42
For j = 2 (nums[j] = 1):
(12 - 1) * 7 = 11 * 7 = 77 maxValue = 77
For j = 3 (nums[j] = 2):
(6 - 2) * 7 = 4 * 7 = 28 maxValue stays 77
Final answer = 77
Complexity Analysis
Time Complexity:
O(n) for prefix max + suffix max + single loop.
Space Complexity:
O(n) for leftMax and rightMax arrays.
Edge Cases
- Strictly increasing array
Best i is always at the left, best k at the right. - All equal numbers
Differences become zero → answer is zero. - nums[j] is the largest among the three
Differences become negative → expression becomes small or zero.
