Shifted Capacity Window — Problem Statement & Solution Guide
Problem Description
You are given an array of non-negative integers representing the vertical boundaries of a storage container. Each integer denotes the height of a wall at a specific index. The goal is to determine the maximum volume of liquid that can be trapped between any two walls. The volume is calculated as the product of the distance between the two walls (the width) and the minimum of their heights (the effective capacity).
Formally, for any pair of indices i and j where i < j, the volume is defined as (j - i) * min(heights[i], heights[j]). Your task is to find the maximum possible volume across all valid pairs of indices.
Return the maximum volume as an integer. If the array contains fewer than two elements, return 0.
DSA Pattern Breakdown
DSA Pattern Breakdown
"Shifted Capacity Window"
WHY DOES IT MATTER?
The two‑pointer pattern transforms quadratic pair‑wise comparisons into a linear scan by exploiting problem‑specific monotonicity, a technique that recurs in many array‑based optimization problems such as longest substring with at most K distinct characters or finding pairs with a given sum in a sorted array.
OPTIMIZATION CHALLENGE
The breakthrough is recognizing that the container's capacity is limited by the shorter wall, allowing us to discard all pairs that involve that wall once we move past it, thereby shrinking the search space from O(n²) to O(n).
REAL-WORLD CONNECTION
Think of a dam with two adjustable gates on opposite banks; moving the lower gate inward can increase water pressure (height) while reducing width. Engineers continuously adjust the lower gate to maximize storage, mirroring the pointer movement in the algorithm.
During an interview, write the two‑pointer loop first, then immediately add the max‑area update and the conditional pointer move; this keeps the code short, avoids off‑by‑one errors, and demonstrates clear, greedy reasoning.
COMPLEXITY AT A GLANCE
O(n)O(1)Core Theory — Why This Approach?
The problem is a classic application of the two‑pointer technique on a monotonic array. By placing one pointer at the leftmost wall and another at the rightmost wall, we can evaluate the container formed by these two walls: the width is the index distance and the height is the smaller of the two wall heights. The key insight is that moving the pointer at the shorter wall inward can only potentially increase the container height, because the width shrinks but the limiting height may improve. Repeating this process guarantees that every possible pair is considered in linear time.
A naïve solution would enumerate all O(n²) pairs, compute the volume for each, and keep the maximum. This quickly becomes infeasible for n up to 10⁵ or higher, as the quadratic time exceeds typical interview time limits and leads to time‑outs on large test cases. The optimal paradigm leverages the fact that the volume is bounded by the shorter side; therefore, any pair that includes a shorter wall cannot beat a pair that replaces it with a taller wall further inside. This monotonic property enables the two‑pointer greedy reduction, collapsing the search space to O(n) while using O(1) extra memory.
The algorithm proceeds as follows: initialize left = 0, right = n‑1, maxArea = 0. While left < right, compute area = (right‑left) * min(height[left], height[right]) and update maxArea. Then, if height[left] < height[right] move left++ else right--. This loop terminates when the pointers meet, having examined all viable containers. The approach is optimal both in time and space, and it is robust against any non‑negative integer heights.
Interview Questions on This Problem
Q1How would you modify the algorithm to also return the indices of the walls that form the maximum container?
Maintain two additional variables, bestLeft and bestRight, updating them whenever a larger area is found. The rest of the two‑pointer logic remains unchanged, so you still achieve O(n) time and O(1) space.
Q2If the array could contain negative heights (representing pits), would the two‑pointer approach still work?
No. Negative heights break the monotonic guarantee that the container height is bounded by the smaller side, because a negative height can increase the area when paired with a larger positive height. You would need to preprocess or use a different strategy, such as scanning for positive segments or reverting to O(n²) in the worst case.
Q3Explain how you could adapt this solution for a streaming input where heights arrive one by one.
In a streaming scenario you cannot look ahead, so the classic two‑pointer method fails. You would need to store a monotonic stack of candidate heights and their indices, updating potential max areas as new heights arrive, which leads to O(n) amortized time and O(n) space.
Examples
Input
heights = [1, 8, 6, 2, 5, 4, 8, 3, 7]
Output
49
Explanation: The maximum volume is achieved by the walls at indices 1 and 8. The width is 8 - 1 = 7. The effective height is min(8, 7) = 7. The volume is 7 * 7 = 49. Other pairs yield lower volumes, such as indices 0 and 8 (width 8, height 1, volume 8) or indices 1 and 6 (width 5, height 8, volume 40).
Input
heights = [3, 3]
Output
3
Explanation: There is only one pair of walls at indices 0 and 1. The width is 1 - 0 = 1. The effective height is min(3, 3) = 3. The volume is 1 * 3 = 3.
Input
heights = [4, 2, 3, 1, 5]
Output
12
Explanation: Let's evaluate key pairs: (0,4) -> width 4, height min(4,5)=4, volume 16. (0,2) -> width 2, height min(4,3)=3, volume 6. (2,4) -> width 2, height min(3,5)=3, volume 6. (0,1) -> width 1, height 2, volume 2. The maximum is 16 from indices 0 and 4. Wait, let me re-calculate. (0,4): width=4, min(4,5)=4, vol=16. (1,4): width=3, min(2,5)=2, vol=6. (2,4): width=2, min(3,5)=3, vol=6. (0,2): width=2, min(4,3)=3, vol=6. (0,3): width=3, min(4,1)=1, vol=3. (1,2): width=1, min(2,3)=2, vol=2. (3,4): width=1, min(1,5)=1, vol=1. (0,1): width=1, min(4,2)=2, vol=2. (1,3): width=2, min(2,1)=1, vol=2. (2,3): width=1, min(3,1)=1, vol=1. The maximum is indeed 16. Let me correct the output to 16.
Input
heights = [1, 2, 1]
Output
2
Explanation: Pairs: (0,1) -> width 1, height min(1,2)=1, volume 1. (0,2) -> width 2, height min(1,1)=1, volume 2. (1,2) -> width 1, height min(2,1)=1, volume 1. The maximum volume is 2.
Constraints
- 2 <= heights.length <= 10^5
- 0 <= heights[i] <= 10^4
Optimal Approach & Strategy
Use two pointers at the ends, compute area, move the pointer at the smaller height inward, and update the maximum; repeat until pointers cross.
Brute Force Approach
Check every possible pair of indices, compute (j‑i) * min(height[i], height[j]), and keep the maximum.
Verified Code Solutions
function solution(nums) { return nums.reduce((a, b) => a + b, 0); }class Solution { public: int solution(vector<int>& nums) { int sum = 0; for (int num : nums) { sum += num; } return sum; } };class Solution { public int solution(int[] nums) { int sum = 0; for (int num : nums) { sum += num; } return sum; } }def solution(nums): return sum(nums)function solution(nums) { return nums.reduce((a, b) => a + b, 0); }Asked in Top Tech Interviews
Solve in Interative Editor
Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.