一.问题描述
给定一个长度为 n
的整数数组 height
。有 n
条垂线,第 i
条线的两个端点是 (i, 0)
和 (i, height[i])
。
找出其中的两条线,使得它们与 x
轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
二.问题思路
对于这个问题。装水的量应该是由两条线中较短的那条的高度,乘以两条线之间的距离决定的。比如说,两条线i和j,高度是h[i]和h[j],那么储水量就是min(h[i], h[j]) * (j - i)。我们需要找到这样的i和j,使得这个乘积最大。
2.1 暴力法
暴力法,就是遍历所有可能的i和j的组合,计算它们的乘积,然后取最大的。 但是这样的话,时间复杂度是O(n²),如果n很大的话,肯定会超时。
代码实现
class Solution {
public:
int maxArea(vector<int>& height) {
int area = 0;
int max_area = -1;
for (int i = 0;i < height.size();i++)
{
for (int j = i + 1;j < height.size();j++)
{
area = (j - i) * min(height[i], height[j]);
if (area > max_area)
{
max_area = area;
}
}
}
return max_area;
}
};
2.2 双指针法
问题思路:
1.双指针法:使用两个指针left
和right
,分别从数组的起始和末尾开始。
2.计算当前容量:当前容量的高度由较短的垂线决定(min(height[left], height[right])
),宽度为两指针的距离(right - left
),容量为高度乘以宽度。
3.更新最大值:每次计算当前容量后,更新最大容量max_area
。
4.移动指针:移动高度较小的指针以寻找可能的更大容量。若左指针的高度较小,则右移左指针;反之左移右指针。
5.终止条件:当left >= right
时,所有可能的容器已遍历完毕,返回最大容量。
代码实现
#include <vector>
#include <algorithm> // 用于min和max函数
using namespace std;
class Solution {
public:
int maxArea(vector<int>& height) {
int max_area = 0;
int left = 0;
int right = height.size() - 1;
while (left < right) {
int current_height = min(height[left], height[right]);
int current_width = right - left;
max_area = max(max_area, current_height * current_width);
// 移动高度较小的指针
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return max_area;
}
};
时间复杂度为O(n)
空间复杂度为O(1)