Balanced Tree Span Evaluator 7 — Problem Statement & Solution Guide
Problem Description
You are given an array of non‑negative integers that represent the heights of vertical lines drawn on a coordinate plane. The i-th element of the array corresponds to a line located at position i with height nums[i]. When two lines are chosen, together with the x‑axis they form a container that can hold a certain amount of water. The capacity of this container equals the horizontal distance between the two lines multiplied by the height of the shorter line. Your task is to determine the maximum amount of water that can be held by any pair of lines in the array.
Input is provided as a single integer n followed by n space‑separated integers. Output a single integer: the largest possible area that can be formed by any two lines. The solution must run in linear time using the two‑pointer technique, as the array can contain up to 10^5 elements.
DSA Pattern Breakdown
DSA Pattern Breakdown
"Balanced Tree Span Evaluator 7"
WHY DOES IT MATTER?
The two‑pointer pattern transforms quadratic pairwise comparisons into a linear scan, a critical skill for optimizing any problem where the answer depends on a pair of indices with a monotonic relationship. Mastery of this pattern directly impacts performance in interview problems involving arrays, strings, and even linked lists.
OPTIMIZATION CHALLENGE
The breakthrough is recognizing that the container’s height is bounded by the shorter line, so discarding that line cannot eliminate any better solution. This insight reduces the search space from O(n²) pairs to a single pass of O(n) moves.
REAL-WORLD CONNECTION
Think of two surveillance cameras placed on a straight road: the area they can jointly monitor is limited by the weaker camera's range and the distance between them. To maximize coverage, you would start with the farthest cameras and iteratively replace the weaker one with a stronger one closer in, mirroring the two‑pointer contraction.
During the interview, write the two‑pointer loop first, then immediately add the max‑area update and the pointer‑movement condition. This keeps the code short, avoids off‑by‑one errors, and demonstrates clear, purposeful reasoning.
COMPLEXITY AT A GLANCE
O(n)O(1)Core Theory — Why This Approach?
The problem is a classic example of the two‑pointer technique applied to a monotonic property. Each index i represents a vertical line of height nums[i]; the water container formed by two lines i and j holds water equal to (j‑i) * min(nums[i], nums[j]). A naive O(n²) scan enumerates every pair, but the key insight is that the container’s capacity is limited by the shorter line. By starting with the widest possible span (the two ends of the array) and iteratively moving the pointer at the shorter line inward, we guarantee that any future container using the discarded line cannot exceed the current best area, because any new width will be smaller while the height cannot increase beyond the taller line. This greedy elimination yields a linear‑time solution while preserving optimality.
Why the naive approach fails on large inputs is simple: for n up to 10⁵ or more, O(n²) operations translate to billions of comparisons, exceeding time limits and memory bandwidth. The optimal paradigm leverages the fact that the function f(i, j) = (j‑i) * min(h[i], h[j]) is unimodal with respect to moving pointers inward; the two‑pointer scan exploits this monotonicity, discarding sub‑optimal candidates without explicit enumeration. This results in O(n) time and O(1) auxiliary space, which is the theoretical lower bound for a single‑pass solution on an unsorted array.
The algorithm also illustrates a broader principle: when a problem’s objective depends on a combination of a distance metric and a limiting value, a greedy two‑pointer contraction often yields the optimal answer. Understanding why moving the shorter line is safe—because any container formed with it and a line further inside will have a reduced width and cannot compensate for its limited height—solidifies the reasoning behind many similar “max‑area” or “min‑difference” problems.
Interview Questions on This Problem
Q1How would you modify the solution if the array could contain negative heights, and the container could also be formed by lines below the x‑axis?
Treat the absolute value of heights for area calculation, but keep track of sign to ensure the container spans the same side of the axis. The two‑pointer logic still applies: move the pointer with the smaller absolute height because the width shrinks while the limiting height cannot increase.
Q2Can you extend the algorithm to return the indices of the two lines that form the maximum container, not just the area?
Yes. Maintain two variables leftBest and rightBest that store the current pointers when a new maximum area is found. Update them whenever maxArea is improved during the scan, and return them after the loop.
Q3Explain how you would adapt the two‑pointer approach for a streaming scenario where heights arrive one by one and you must output the maximum container seen so far after each insertion.
In a streaming model you cannot retroactively move the left pointer, so you maintain a deque of candidate lines sorted by decreasing height. For each new height at position i, compute area with the earliest candidate (largest width) and update max. Then prune candidates whose height is less than the new height from the back, ensuring O(1) amortized per element.
Examples
Input
9 1 8 6 2 5 4 8 3 7
Output
49
Explanation: The optimal pair is the lines at indices 1 and 8 (heights 8 and 7). The width between them is 7, the shorter height is 7, so the area is 7 * 7 = 49. No other pair yields a larger area.
Input
5 1 1 1 1 1
Output
4
Explanation: All heights are equal to 1. The widest pair is the first and last lines, with a width of 4. The area is 4 * 1 = 4, which is the maximum possible.
Input
4 4 3 2 1
Output
4
Explanation: Checking all pairs: - (0,1): 1 * min(4,3) = 3 - (0,2): 2 * min(4,2) = 4 - (0,3): 3 * min(4,1) = 3 - (1,2): 1 * min(3,2) = 2 - (1,3): 2 * min(3,1) = 2 - (2,3): 1 * min(2,1) = 1 The maximum area is 4, achieved by indices 0 and 2.
Input
3 0 0 0
Output
0
Explanation: All heights are zero, so any pair yields an area of 0. The maximum is therefore 0.
Input
7 5 4 3 2 1 4 5
Output
30
Explanation: The best pair is indices 0 and 6 (heights 5 and 5). The width is 6, the shorter height is 5, giving an area of 6 * 5 = 30. No other pair produces a larger area.
Constraints
- 2 <= nums.length <= 100000
- 0 <= nums[i] <= 1000000000
- The input array is 0-indexed.
- The answer fits within a 64‑bit signed integer.
- The algorithm must run in O(n) time and O(1) additional space.
Optimal Approach & Strategy
Initialize two pointers at the array ends, compute area, move the pointer at the shorter line inward, and repeat, updating the maximum area each step.
Brute Force Approach
Check every possible pair of lines, compute the area, and keep the maximum. This requires two nested loops.
Verified Code Solutions
function solution(nums) {
if (nums.length < 2) return Math.max(...nums);
nums.sort((a, b) => a - b);
return nums[nums.length - 1] + nums[nums.length - 2];
}class Solution {
public:
int solution(vector<int>& nums) {
if (nums.size() < 2) return *max_element(nums.begin(), nums.end());
sort(nums.begin(), nums.end());
return nums.back() + *(nums.end() - 2);
}class Solution {
public int solution(int[] nums) {
if (nums.length < 2) return Arrays.stream(nums).max().getAsInt();
Arrays.sort(nums);
return nums[nums.length - 1] + nums[nums.length - 2];
}def solution(nums):
if len(nums) < 2: return max(nums)
nums.sort()
return nums[-1] + nums[-2]function solution(nums) {
if (nums.length < 2) return Math.max(...nums);
nums.sort((a, b) => a - b);
return nums[nums.length - 1] + nums[nums.length - 2];
}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.