You are given an integer array height
of length n
. There are n
vertical lines drawn such that the two endpoints of the i
th line are (i, 0)
and (i, height[i])
.
Find two lines that together with the x-axis form a container, such that the container contains the most water.
Return the maximum amount of water a container can store.
Notice that you may not slant the container.
Example 1:
Input: height = [1,8,6,2,5,4,8,3,7]
Output: 49
Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
Example 2:
Input: height = [1,1]
Output: 1
Constraints:
n == height.length
2 <= n <= 10^5
0 <= height[i] <= 10^4
Solve this problem efficiently. What is the time and space complexity of your solution? Can you handle edge cases gracefully (e.g., empty array, array with one element, etc.)?
# Maximum Area Container Problem
This problem asks us to find the maximum amount of water a container can store, given an array of heights representing vertical lines. The container is formed by two lines and the x-axis. We cannot slant the container.
## Naive Solution
The brute-force approach is to check every possible pair of lines and calculate the area formed by each pair. We can do this by iterating through all possible pairs of indices (i, j) in the `height` array and calculating the area as `min(height[i], height[j]) * (j - i)`. We then keep track of the maximum area found so far.
```python
def max_area_naive(height):
max_area = 0
for i in range(len(height)):
for j in range(i + 1, len(height)):
area = min(height[i], height[j]) * (j - i)
max_area = max(max_area, area)
return max_area
# Example usage
height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
print(f"Maximum area (naive): {max_area_naive(height)}") # Output: 49
A more efficient approach is to use the two-pointer technique. We initialize two pointers, left
and right
, at the beginning and end of the height
array, respectively. In each iteration, we calculate the area formed by the lines at left
and right
as min(height[left], height[right]) * (right - left)
. We update the maximum area found so far. Then, we move the pointer pointing to the shorter line towards the center. This is because moving the pointer pointing to the taller line will always result in a smaller area (since the width decreases and the height is limited by the shorter line).
def max_area_optimal(height):
left = 0
right = len(height) - 1
max_area = 0
while left < right:
area = min(height[left], height[right]) * (right - left)
max_area = max(max_area, area)
if height[left] < height[right]:
left += 1
else:
right -= 1
return max_area
# Example usage
height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
print(f"Maximum area (optimal): {max_area_optimal(height)}") # Output: 49
n
times, where n
is the length of the height
array. Therefore, the time complexity is O(n^2).while
loop iterates at most n
times. Therefore, the time complexity is O(n).min(height[0], height[1]) * 1
.Here's an updated version of the optimal solution that explicitly handles edge cases:
def max_area_optimal_with_edge_cases(height):
if not height or len(height) < 2:
return 0
left = 0
right = len(height) - 1
max_area = 0
while left < right:
area = min(height[left], height[right]) * (right - left)
max_area = max(max_area, area)
if height[left] < height[right]:
left += 1
else:
right -= 1
return max_area
# Example usage with edge cases
height1 = []
height2 = [5]
height3 = [3, 7]
height4 = [0, 0, 0]
height5 = [1, 8, 6, 2, 5, 4, 8, 3, 7]
print(f"Maximum area (edge case 1): {max_area_optimal_with_edge_cases(height1)}") # Output: 0
print(f"Maximum area (edge case 2): {max_area_optimal_with_edge_cases(height2)}") # Output: 0
print(f"Maximum area (edge case 3): {max_area_optimal_with_edge_cases(height3)}") # Output: 3
print(f"Maximum area (edge case 4): {max_area_optimal_with_edge_cases(height4)}") # Output: 0
print(f"Maximum area (edge case 5): {max_area_optimal_with_edge_cases(height5)}") # Output: 49