在编程领域,最大盛水容器问题是一个经典的算法题。该问题的任务是从给定的一系列高度中找出两条线,使它们与x轴共同形成的“容器”能够盛最多的水。本文将详细探讨该问题的背景、解决方案以及实现代码。
问题描述
给定一个长度为 n
的整数数组 height
,其中每个元素表示垂线的高度。我们需要找出两条线(即数组中的两个元素),使得它们与x轴共同形成的容器可以容纳最多的水。
例如,考虑输入:
height = [1,8,6,2,5,4,8,3,7]
在这个例子中,返回的最大水容量是 49
。
解题思路
1. 容器的面积计算
在数组中,两个线段的横坐标分别为 i
和 j
,对应的高度为 height[i]
和 height[j]
。形成的容器的面积可以通过以下公式计算:
这里:
min(height[i], height[j])
为容器的高度;(j - i)
为容器的宽度。
2. 双指针策略
为了找到最大的水容量,我们采用双指针的方法。利用两个指针分别指向数组的两端,逐步向中心逼近。具体步骤如下:
- 初始化两个指针,
left
指向数组的开始位置0
,right
指向数组的结束位置n-1
。 - 计算当前容器的面积,并用变量
maxArea
存储每次计算的最大值。 - 比较当前两条线的高度,移动较低的那条线。若
height[left] < height[right]
,则将left
向右移动;否则,移动right
向左移动。 - 重复上述过程,直到
left
和right
指针相遇。
3. 时间复杂度与空间复杂度
本算法的时间复杂度为 O(n),因为每个元素最多被访问一次;空间复杂度为 O(1),只使用了常数级别的额外空间。
代码实现
以下是使用 Java 语言实现的代码:
class Solution {
public int maxArea(int[] height) {
int left = 0; // 左指针
int right = height.length - 1; // 右指针
int maxArea = 0; // 最大面积
while (left < right) {
int currentArea = Math.min(height[left], height[right]) * (right - left);
maxArea = Math.max(maxArea, currentArea);
// 移动较短的那条线的指针
if (height[left] < height[right]) {
left++; // 向内移动左指针
} else {
right--; // 向内移动右指针
}
}
return maxArea; // 返回最大面积
}
}
代码解析
- 指针初始化:左指针
left
设置为0
,右指针right
设置为数组长减一。 - 面积计算:我们使用
Math.min()
函数获取较小的高度,并计算当前面积。 - 更新最大面积:使用
Math.max()
比较当前面积和最大面积,并更新maxArea
。 - 移动指针:在比较两个高度后,移动较短的那条线的指针以寻找可能的更大面积,直到两个指针相遇。
示例与测试
示例
考虑输入 height = [1,8,6,2,5,4,8,3,7]
:
- 初始化时,
left = 0
,right = 8
,计算第一次面积为min(1, 7) * (8 - 0) = 8
。 - 移动指针,
left
变为1
,计算面积为min(8, 7) * (7 - 1) = 49
,更新最大面积。 - 再次移动指针,过程继续,最终得到最大面积为
49
。
测试用例
你可以使用下列测试用例来验证实现的正确性:
// 示例测试
Solution solution = new Solution();
System.out.println(solution.maxArea(new int[]{1,8,6,2,5,4,8,3,7})); // 输出: 49
System.out.println(solution.maxArea(new int[]{1,1})); // 输出: 1
System.out.println(solution.maxArea(new int[]{4,3,2,1,4})); // 输出: 16
System.out.println(solution.maxArea(new int[]{1,2,1})); // 输出: 2
结论
最大盛水容器问题通过双指针方法有效解决了在一维数组中寻找两条线段的最大盛水容量的问题。该算法不仅高效,而且实现简单。
希望你喜欢这篇文章!请点关注和收藏吧。祝关注和收藏的帅哥美女们今年都能暴富。如果有更多问题,欢迎随时提问