原题
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.
Note: You may not slant the container and n is at least 2.
翻译
给定n个非负整数a 1, 2,…其中每个表示坐标点(i, ai)。
直线的两个端点是(i, ai)和(i, 0)。
找到两条直线,与x轴一起形成一个容器,这样容器就包含了最多的水。
嗯,先让我们来看一下题目。What a fucking thing is this?
莫慌,我们先上张图,帮助理解(PS画风直击灵魂)
大概意思就是,Y轴上的两个点,连成的线,与另外一根线加上X轴组合成一个容器,这些线能够组合成的容器中,装水最多的是哪一组,如图则为画阴影的部分,嗯如果这也算阴影的话,也就是点(1,a1)和(4,a4)组合成的容器。
例如int[] height = {3,5,7,9,10,2,1,12} 中能组合成最大容器的点为(4,9)和(8,12),返回的值则为(8-4)*(Math.min(9,12))=36
public int maxArea(int[] height) {
int result = 0;
for (int i = 0; i < height.length; i++) {
for (int j = height.length - 1; j >= 0; j--) {
int temp = (j - i) * Math.min(height[i], height[j]);
result = Math.max(result, temp);
}
}
return result;
}
是不是很简单?抱歉,如果真这么简单,LeetCode也不至于分级属于中等难度了,拿去一提交,发现
Submission Result: Time Limit Exceeded
提交超时,看样子虽然题目中没有给出时间复杂度的要求,但是最终校验的时候还是会有这样的,既然这样,这套思路就不太能走得通了,因为双层循环优化下去,也无法有显著的性能提升。
既然这样,我们再回到上面那个例子int[] height = {3,5,7,9,10,2,1,12} ,如果让我们人工来找出最大的一组数据怎么会怎么找呢?
是不是先从左往右找到一个较大的数字,比如7,然后再从右往左找出一个较大的数,12,然后计算,再算下9和10就差不多了。既然这样,我们程序其实也可以这样写。
不过程序无法估计出一个合适的位置找到较大的数进行,那么我们就从最左边和最右边,找到一个数,但是这次不是两边都动了,我们前面计算的时候都知道,7算完12不动,因为12比7要大,如果12都不行的话,那么7就更不行了,毕竟都是移动一位。
至于原理,根据题目的特殊性,X每次移动都是"1",而Y的变化最少是"1",那么我们只需要确保每次计算的高都比上一次的要高,那么容器就可以确保是最大的。我们每次计算都是记录的两个最大高度的值,这样得到的结果也就是最大的,
文字说起来比较空洞,直接上代码吧
public int maxArea(int[] height) {
int i =0, j = height.length - 1;
int result = 0;
while (i != j){
int temp = (j - i) * Math.min(height[i], height[j]);
result = Math.max(result, temp);
if (height[i] > height[j])
j--;
else
i++;
}
return result;
}