题目
给定一个长度为 n
的整数数组 height
。有 n
条垂线,第 i
条线的两个端点是 (i, 0)
和 (i, height[i])
。
找出其中的两条线,使得它们与 x
轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
示例
输入:[1,8,6,2,5,4,8,3,7] 输出:49 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
分析
笔者最初的做法是类似于“滑窗”的思想,每个点从间距1开始递增直到最大边界,进而不断计算面积并维护最大值。但这样做容易超时!!!因此我们需要优化,双指针是一个不错的选择。它可以帮助我们通过从两端开始逐步更新指针位置,缩小问题的搜索空间。
以 [1,8,6,2,5,4,8,3,7] 为例:
[1, 8, 6, 2, 5, 4, 8, 3, 7] area=8
^ ^
移动数字较小的那个指针
[1, 8, 6, 2, 5, 4, 8, 3, 7] area=49
^ ^
[1, 8, 6, 2, 5, 4, 8, 3, 7] area=18
^ ^
[1, 8, 6, 2, 5, 4, 8, 3, 7] area=40
^ ^
[1, 8, 6, 2, 5, 4, 8, 3, 7] area=16
^ ^
[1, 8, 6, 2, 5, 4, 8, 3, 7] area=15
^ ^
[1, 8, 6, 2, 5, 4, 8, 3, 7] area=4
^ ^
[1, 8, 6, 2, 5, 4, 8, 3, 7] area=6
^ ^
[1, 8, 6, 2, 5, 4, 8, 3, 7]
^
为什么移动数字较小那个指针?
因为水量是由容器的最小高度和宽度决定的。移动较短的线(较小的数字)有可能找到更高的线,从而增加容器的最小高度,进而提高水量,减少不必要的计算和比较,提高算法效率。
双指针法
时间复杂度:O()
空间复杂度:O(1)
class Solution {
public:
int maxArea(vector<int>& height) {
int max_water = 0; // 用于存储最大水量
int left = 0; // 左指针
int right = height.size() - 1; // 右指针
while (left < right) {
// 计算当前容器的水量
int current_water = min(height[left], height[right]) * (right - left);
max_water = max(max_water, current_water); // 更新最大水量
// 移动较小的那一侧的指针
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return max_water; // 返回最大水量
}
};