这个问题是一个经典的算法问题,通常称为“盛最多水的容器”。目标是找到两个边界线(高度数组中的元素),使得它们与x轴共同构成的容器能够容纳最多的水。以下是该问题的详细思路和代码讲解。
思路
-
输入: 给定一个非负整数数组
height
,其中每个元素表示纵坐标上的高度。图形的两条边分别由数组中的元素代表。 -
计算容器容量:
- 容器的容量由两条边及其间的距离决定。具体而言,如果选择了
height[i]
和height[j]
作为边界,容器的容量(即能够容纳的水量)为:
[
\text{容量} = \text{min}(height[i], height[j]) \times (j - i)
] - 在这个公式中,
min(height[i], height[j])
确定了水的高度,而(j - i)
是这两个边之间的水平距离。
- 容器的容量由两条边及其间的距离决定。具体而言,如果选择了
-
双指针方法:
- 使用两个指针:一个指向数组的开始(
left
),一个指向数组的末尾(right
)。 - 计算当前的容量并更新最大容量。
- 移动较短的边界指针(即
height[left]
或height[right]
),因为移动更高的边不会增加水容量,而可能会减少水平距离。
- 使用两个指针:一个指向数组的开始(
-
终止条件: 两个指针相遇,即完成了所有可能的边界组合。
代码实现
以下是上述思路的 Python 代码实现:
def max_area(height):
left = 0 # 左指针
right = len(height) - 1 # 右指针
max_volume = 0 # 初始化最大容量
while left < right:
# 计算当前容量
current_volume = min(height[left], height[right]) * (right - left)
# 更新最大容量
max_volume = max(max_volume, current_volume)
# 移动指针
if height[left] < height[right]: # 移动较短的一边
left += 1
else:
right -= 1
return max_volume # 返回最大容量
# 示例
heights1 = [1, 8, 6, 2, 5, 4, 8, 3, 7]
print(max_area(heights1)) # 输出: 49
heights2 = [1, 1]
print(max_area(heights2)) # 输出: 1
代码解释
-
函数定义:
max_area(height)
,接受一个数组height
。 -
初始化指针和变量:
left
和right
分别指向数组的开始和末尾。max_volume
用于记录当前找到的最大容量。
-
循环条件: 当
left
小于right
时执行循环。 -
计算当前容量:
- 使用
min(height[left], height[right])
计算当前容器的有效高度。 - 计算宽度为
right - left
,并更新max_volume
。
- 使用
-
移动指针:
- 根据当前边的高度,移动较短的边指针,以尝试找到更大的容量。
-
返回最大面积: 循环结束后,返回找到的最大水容量。
示例运行
-
输入
[1, 8, 6, 2, 5, 4, 8, 3, 7]
:- 结果为
49
,这是高度8
和7
之间的面积(宽7
,高度7
)。
- 结果为
-
输入
[1, 1]
:- 结果为
1
,因为两条边都是1
,且距离为1
。
- 结果为
总结
通过使用双指针的方法,算法的时间复杂度为 O(n),只需一次遍历即可找到最大容器容量。这种方法有效地减少了计算所需的时间,同时避免了过多的组合计算。