给定一个长度为 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。输入:height = [1,1]
输出:1
n == height.length
2 <= n <= 105
0 <= height[i] <= 104
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
if (!height || height.length < 2) {
return 0;
}
let max = 0;
let res = 0;
for (let i = 0; i < (height.length - 1); i++) {
for (let j = i + 1; j < height.length; j++) {
if (height[i] < height[j]) {
res = height[i] * (j - i);
} else {
res = height[j] * (j - i);
}
if (res > max) {
max = res;
}
}
}
return max;
};耗时久,性能差
这个问题是著名的“盛水最多的容器”问题,可以通过双指针法来高效地解决。该算法的关键在于逐步缩小范围,同时记录能够容纳的最大水量。
给定一个整数数组 height,我们需要找到两个索引 i 和 j(其中 i < j),使得 min(height[i], height[j]) * (j - i) 的值最大。这就是容器的最大水容量。
初始化双指针:
设置两个指针,左指针 left 初始化为数组的起始位置 0,右指针 right 初始化为数组的终止位置 n-1,其中 n 是数组的长度。
计算当前水容量:
在每一步中,计算由 left 和 right 指针所确定的容器的水容量:min(height[left], height[right]) * (right - left)。
如果这个容量比目前记录的最大容量要大,就更新最大容量。
移动指针:
由于水容量受限于短板(较短的那一边),我们选择移动高度较小的一端指针(即 height[left] 和 height[right] 中较小的那一个)来尝试寻找更长的高度。
如果 height[left] < height[right],就把 left 指针右移(left++),否则就把 right 指针左移(right--)。
重复步骤2和步骤3,直到两个指针相遇。
输出结果:
当两个指针相遇时,已经找到了最大水容量,输出这个最大值。
def maxArea(height):
# 初始化双指针
left, right = 0, len(height) - 1
max_water = 0
while left < right: # 计算当前容器的水容量
current_water = min(height[left], height[right]) * (right - left)
# 更新最大水容量
max_water = max(max_water, current_water)
# 移动指针
if height[left] < height[right]:
left += 1
else:
right -= 1
return max_water# 示例测试heights = [1,8,6,2,5,4,8,3,7]print(maxArea(heights)) # 输出: 49时间复杂度:O(n),其中 n 是数组的长度。每个元素最多被访问一次。
空间复杂度:O(1),只使用了常量级别的额外空间。
对于 heights = [1,8,6,2,5,4,8,3,7],上述代码将输出 49。这对应于垂线索引 1 和 8,它们之间的距离是 7,较短的垂线高度是 7,因此水容量是 7 * 7 = 49。
这个算法通过聪明地选择指针移动来高效地找到最优解,并且避免了冗余计算。