力扣-hot100(盛最多水的容器-双指针)
11. 盛最多水的容器
中等
给定一个长度为 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。
-
n == height.length
-
2 <= n <= 105
-
0 <= height[i] <= 104
思路
容器的长是由两直线(宽)的距离决定的,容器的高是两直线中最短的那根确定的。所以我只需要两两遍历每条边,求一个max不就行了吗。
很明显 n = 10^5, n^2的操作是会超时的
代码如下
class Solution {public int maxArea(int[] height) {// 容器的长是由两直线的距离决定的,容器的高是两直线中最短的那根int n = height.length;int maxValue = 0;// 左边长for(int left = 0; left < n; left ++){// 右边长for(int right = left; right < n; right ++){int h = Math.min(height[left], height[right]);int c = right - left;maxValue = Math.max(maxValue, h * c);}}return maxValue;} }
改进
实事上并不是每条边(高)都是有价值的,宽的价值是很好确定的,最两侧的边,为宽的最大权重。
思路:抓一头,先让宽的价值最大化,此时的边是最两侧的,为了不漏掉中间有很高的,肯定要从两侧往中间移动,移动哪条? 那肯定是移动更矮的那根, 高的那根更能创造价值
补充: 这样做会不会漏掉,这里漏掉的情况只可能有一种,就是当两个高相等时,移动了随机一根,但是要明确的是高的长度是由最短的那根确定下来的,即便你后面有很长的,也会被这两根相同的限制,所以不论移动哪根都是一样的。如果你后面有很短的那更不可能了,后面的宽和高都小的话,面积只会比当前的更小,我们求的是最大面积。
代码如下:
class Solution {public int maxArea(int[] height) {// 让宽处于最大,即最两侧int left = 0, right = height.length - 1;// 定义最大面积int maxValue = 0;// 宽、高int w, h;while(left < right){// 宽为两者之间的距离w = right - left;// 高取最小的那根h = Math.min(height[left], height[right]);// 面积maxValue = Math.max(maxValue, w * h);// 让更矮的那端向中间移动if(height[left] < height[right]) left ++;else right --;}return maxValue;} }