You are given an integer array height
of length n
. There are n
vertical lines drawn such that the two endpoints of the i<sup>th</sup>
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:
Given the input height = [1,8,6,2,5,4,8,3,7]
, what is the maximum amount of water the container can store? Explain your reasoning.
Example 2:
Given the input height = [1,1]
, what is the maximum amount of water the container can store?
Explain the time and space complexity of your solution. What are some edge cases to consider?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to finding the container with the most water involves checking every possible pair of vertical lines. For each pair, we calculate the area of the container they form. We then keep track of the largest area found so far and ultimately return that maximum area.
Here's how the algorithm would work step-by-step:
def max_area_container_brute_force(heights):
max_area = 0
# Iterate through all possible pairs of lines
for first_line_index in range(len(heights)):
for second_line_index in range(first_line_index + 1, len(heights)):
# Determine the height of the container
# formed by the current pair of lines.
shorter_line = min(heights[first_line_index], heights[second_line_index])
# Calculate the width of the container
container_width = second_line_index - first_line_index
# Calculate the area of the container
current_area = shorter_line * container_width
# Keep track of the maximum area found
if current_area > max_area:
max_area = current_area
return max_area
The core idea is to find the largest possible container formed by two vertical lines. We begin by considering the widest possible container and then iteratively narrow it down, always moving the shorter of the two lines inward, since this is the only way to potentially find a taller container.
Here's how the algorithm would work step-by-step:
def max_area(heights):
max_water = 0
left_index = 0
right_index = len(heights) - 1
while left_index < right_index:
# Calculate area based on the shortest line.
current_water = min(heights[left_index], heights[right_index]) * \
(right_index - left_index)
max_water = max(max_water, current_water)
# Move the pointer of the shorter line.
if heights[left_index] < heights[right_index]:
# Moving the left pointer has potential for larger area
left_index += 1
else:
# Moving right pointer has potential to find larger area
right_index -= 1
return max_water
Case | How to Handle |
---|---|
Empty or null height array | Return 0 if the input array is null or empty, as no container can be formed. |
Array with only one element | Return 0 if the array has only one element, as a container needs at least two lines. |
Array with all elements equal to 0 | The algorithm should return 0 as the maximum water that can be contained is zero. |
Array with all elements having the same value (non-zero) | The algorithm should correctly calculate the area using the distance between the first and last element multiplied by that value. |
Array with a very large number of elements (performance) | The two-pointer approach is O(n) and efficient enough for large arrays; avoid brute force. |
Integer overflow when calculating area | Use `long` data type for area calculation to prevent integer overflow if the input values are large. |
Array with extremely large height values | Ensure the algorithm still functions correctly and doesn't suffer from numerical instability or unexpected behavior due to large numbers, and it should still return an integer. |
Array where the maximum water is formed at the edges. | The algorithm must consider the edges properly when comparing areas and updating pointers. |