原题:
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.
题目理解:
题目的意思就是给定一个数组分布在XY坐标系中,然后求解哪两个元素和X轴组成一个水桶之后能够装的水最多。例如有a[i]和a[j]两个元素中(i<j)比较小的是a[i],则找出a[i]*(j-i)最大的值。
首先想到的解法就是列举所有的可能情况,然后进行大小的比较。代码如下:
public class Solution {
public int maxArea(int[] height) {
int maxarea = 0;
for (int i = 0; i < height.length; i++)
for (int j = i + 1; j < height.length; j++)
maxarea = Math.max(maxarea, Math.min(height[i], height[j]) * (j - i));
return maxarea;
}
这样做的话,算法的时间复杂度是
O
(
n2
)。这个算法的效率是不高的,做了太多的无用的比较。
对上面的算法进行了优化,减少了部分无用的比较,代码如下:
class Solution {
public int maxArea(int[] height) {
int laragArea = 0;
for (int i = 0; i < height.length-1; i++){
if (height[i] == 0){
continue;
}
for (int j = i+1+laragArea/height[i]; j < height.length; j++){
int min = Math.min(height[i], height[j]);
int area = min * (j-i);
if (area > laragArea){
laragArea = area;
}
}
}
return laragArea;
}
}
该算法的主要想法是跳过开始就不可能成为最大面积的元素,因此对比第一个解法,在第二重循环中,j并不是从i+1开始,而是从可能成为最大面积的i+1+laragArea/height[i]开始,从而减少了部分比较。然而该算法在极坏的情况下,时间复杂度仍为O(n2),和第一个解法没有差别。
由此有了第三种解法,解法的思想是离得远的两个元素最有可能成为最大面积。设置两个指针,一个从0开始,一个从最后开始,每次均比较这两个元素组成的面积和保存的最大面积,然后将较小的元素的指针向中间移动,知道两个指针重合的时候,就可以得到最大的面积了。
class Solution {
public int maxArea(int[] height) {
int laraArea = 0;
int start = 0;
int end = height.length-1;
while (start < end){
laraArea = Math.max(laraArea, Math.min(height[start], height[end]) * (end - start));
if (height[start] > height[end]){
end--;
}else{
start++;
}
}
return laraArea;
}
}