# 11.盛水最多的容器
# 题目描述 (opens new window)
TIP
标签: 贪心、数组、双指针
# 算法思路
本题是一道经典的双指针题目,可以按照这个思路去理解。
[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
1
2
2
在初始阶段,左右两个指针分别指向数组的左右两侧,它们可以容纳的水量为 min(1,7) * 8 = 8
。
这个时候我们需要移动指针,移动哪一个指针呢? 直觉告诉我们,应该移动数字较小的那个 (就是我们所说的左指针),因为,容纳水量是由:
两个指针指向的数字中较小值 * 指针之间的距离
如果我们移动数字较大的指针,那么前者「两个指针指向的数字中的较小值」不会增加,后者「指针之间的距离」会减小,那么这个乘积会减小,这并不是我们期望的结果。
因此,我们移动数字较大的那个指针是不合理的,因此,我们移动数字较小的那个指针。
具体的:
需要定义两个指针分别指向数组的左右两端, 然后两个指针向中间搜索,每移动一次算一次值并和结果比较取较大的,容器装水量的算法是找出左右两个边缘中较小的那个乘以两边的距离。
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function (height) {
let res = 0, i = 0, j = height.length - 1;
// 不能重合
while (i < j) {
res = Math.max(res, Math.min(height[i], height[j]) * (j - i))
if (height[i] < height[j]) {
i++
} else {
j--
}
}
return res
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function maxArea(height: number[]): number {
let res: number = 0
let left: number = 0
let right: number = height.length - 1;
while (left < right) {
res = Math.max(res, Math.min(height[left], height[right]) * (right - left))
if (height[left] < height[right]) {
left++
} else {
right--
}
}
return res
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//
class Solution {
// 返回int类型的变量
public int maxArea(int[] height) {
int i = 0, j = height.length - 1, res = 0;
while(i < j) {
res = height[i] < height[j] ?
Math.max(res, (j - i) * height[i++]):
Math.max(res, (j - i) * height[j--]);
}
return res;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 复杂度分析
- 时间复杂度:O(N),双指针总计最多遍历整个数组一次
- 空间复杂度:O(1),只需要额外的常数级别的空间