# 盛最多水的容器(11)

# 题目

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai)(i, 0)

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

# 示例

输入:[1,8,6,2,5,4,8,3,7] 输出:49

# 算法

# 暴力法

export const maxArea = (height) => {
	let max = 0;
	for (let i = 0; i < height.length - 1; i++) {
		for (let j = i + 1; j < height.length; j++) {
			if (max < (j - i) * Math.min(height[j], height[i])) {
				max = (j - i) * Math.min(height[j], height[i]);
			}
		}
	}
	return max;
};
1
2
3
4
5
6
7
8
9
10
11

# 双指针

首尾指针分别指向第一块和最后一块木板,之后每次都移动较小的那一块木板后计算容积,与当前最大值比较

因为如果移动较大的木板,则容积一定缩小(间距缩小、高度缩小);但是如果移动的是较小的木板,则容易可能变大(间距缩小、高度增大)

当容积变大时(移动小板后),会抛弃一组以原来的小板为边的可能的容积,但如果移动后的容积变大,则抛弃的容器不可能使之成为最大值,所以被抛弃的这些可能的值不会影响最大值

export const maxArea = (height) => {
	let l = 0,
		r = height.length - 1;
	let max = 0;
	while (l < r) {
		if (max < Math.min(height[l], height[r]) * (r - l)) {
			max = Math.min(height[l], height[r]) * (r - l);
		}
		if (height[l] < height[r]) {
			l++;
		} else {
			r--;
		}
	}
	return max;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16