11. Container With Most Water
题目描述
Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
给定一组非负整数 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1,a2,...,an,每一个代表了 ( i , a i ) (i,a_i) (i,ai)这样的一个点,N个垂直的线从这n个定点 ( i , a i ) (i,a_i) (i,ai)到 ( i , 0 ) (i,0) (i,0), 取其中任意两个线,加上x轴构成一个三边的容器,求出其中能够装最多的水的大小。
Note: You may not slant the container and n is at least 2.
不可以倾斜容器,n至少是2
思路
首先我们想一想,两个线的组合应该有n(n - 1)/2种情况
穷举的话我们就是全部算出来,然后其中最大的就是结果
但是呢,这样穷举的话,在本题是超时的,很明显他需要我们给出更好的解法。
那么想一想,我们看到这个问题之后是怎么解决的呢,我可能会先看比较距离大的,因为它的距离远,面积其实就是距离×较小的一边。然后如果中间有更大的我就算一算会不会变大面积。
我们可以维持两个指针分别指向头尾,然后向中间靠拢,寻找更大的。这里重点是怎么移动指针。
我们假设当前头指针为i,尾指针为j,height[i] < height[j],那么这样的话,如果i不动的话,我将j尾指针前移,也就是减小。找到一个比height[j]大的,但是由于距离小了,而且要取较小的一边(此时还是height[i]),所以此时一定小于刚才的情况(边不变,距离减小了)那么就没有必要了。所以我们移动两边中较小的一边。
代码
// 辅助函数
max = (...arr) => {return arr.reduce((red,item)=>{ if (item > red) red = item; return red})}
min = (...arr) => {return arr.reduce((red,item)=>{ if (item < red) red = item; return red})}
var maxArea = function(height) {
let i = 0;
let j = height.length - 1;
let maxc = min(height[i], height[j]) * (j - i);
while (i < j) {
maxc =max(maxc, min(height[i], height[j]) * (j - i));
height[i] < height[j] ? ++i : --j; // 移动较小的一边的头/尾指针
}
return maxc;
};