题目地址(11. 盛最多水的容器)
https://leetcode.cn/problems/container-with-most-water/
题目描述
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1
提示:
n == height.length
2 <= n <= 105
0 <= height[i] <= 104
前置知识
公司
- 暂无
思路
- 双指针法,并向中间移动较矮的那个指针
关键点
- 证明双指针法的正确性
双指针代表的是 可以作为容器边界的所有位置的范围。在一开始,双指针指向数组的左右边界,表示 数组中所有的位置都可以作为容器的边界,因为我们还没有进行过任何尝试。在这之后,我们每次将 对应的数字较小的那个指针 往 另一个指针 的方向移动一个位置,就表示我们认为 这个指针不可能再作为容器的边界了。
考虑第一步,假设当前左指针和右指针指向的数分别为 x和 y,不失一般性,我们假设 x <= y。同时,两个指针之间的距离为 t。那么,它们的容器的容量为:mix(x, y) * t = x * t
我们可以断定,如果我们保持左指针的位置不变,那么无论右指针在哪里,这个容器的容量都不会超过 x * t 了。
这个左指针对应的数不会作为容器的边界了,那么我们就可以丢弃这个位置,将左指针向右移动一个位置,此时新的左指针于原先的右指针之间的左右位置,才可能会作为容器的边界。
这里有一个核心点,如果x == y,怎么办?
- 可以任意移动左指针或者右指针。为什么?因为,此时如果想要找到更大的,就不可能以此时的左指针或者右指针为边界,min(x, y) * t是以x, y为边界时,这段区域的最大值。所以如果要找到最大的,只能左右边界不是x, y,只能都在里面。
代码
- 语言支持:Java
Java Code:
class Solution {
public int maxArea(int[] height) {
if (height == null || height.length < 2) {
return 0;
}
int left = 0;
int right = height.length - 1;
int maxArea = 0;
while (left < right) {
maxArea = Math.max(maxArea, (right - left) * Math.min(height[left], height[right]));
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return maxArea;
}
}
Go Code:
func maxArea(height []int) int {
if height == nil || len(height) < 2{
return 0;
}
left, right, area := 0, len(height) - 1, 0
for left < right {
tmp := min(height[left], height[right]) * (right - left)
if area < tmp {
area = tmp
}
if height[left] < height[right] {
left++
} else {
right--
}
}
return area
}
func min(x,y int) int {
if x < y {
return x
} else {
return y
}
}
复杂度分析
令 n 为数组长度。
- 时间复杂度:
- 空间复杂度:
网友评论