leetcode11. 盛最多水的容器

题目大意:找出两条直线,使得两条直线与水平轴构成的容器能装的水最多

题目分析:如果使用挨个遍历,枚举出所有可能的两条直线a[i],a[j],那么最大的水量就是min(a[i],a[j])*(j-i)

这种算法的时间复杂度是O(n^2),显示超时。

下面介绍一种O(n)时间复杂度的做法:

起初,用两个指针i,j分别指向最开始和最末尾的两个数值height[i],height[j].  将两者中的较小者移动,也就是说,如果height[i]>height[j],则指针j前移,否则i后移。更新移动过程中的可装水的最大值,直到i和j相遇,则移动结束。

为什么要将height[i],height[j]中的较小者移动呢?因为这样才能使得可装水的量增大。假设将两者的较大者j移动,j--,那么如果移动后height[j]>原先的height[j],则面积反而变小了(高度没变,长度变小了)。如果移动后height[j]<=height[i],则面积会更小(高度变小了,长度也变小了)。但是如果将较小者移动,那么会是什么效果呢?假设i后移,i++,若新的height[i]>原先的height[i],那么面积会增大,达到了我们的效果。

那这样做是否会有遗漏呢?假设height[0]<height[len-1],i=0,j=len-1,然后进行i++操作,那么之后就不会考虑以height[0]为左壁的容器,这样真的可以嘛?答案是可以的,因为以height[0]为左壁的容器可装水的最大容量,就是以height[0]为左壁,以height[len-1]为右壁的容器的容量,(此时的间距是最大的),容量为(len-1)*a[0]。这种情况考虑过了,所以之后就可以不用考虑height[0]了,可以放心的i++了。

代码展示:

class Solution {
public:
    int maxArea(vector<int>& height) {
        int len = height.size();
        int max = 0;
        int temp = 0;
        for(int i=0,j=len-1;i<j;)
        {
            temp = min(height[i],height[j]);
            if((temp*(j-i))>max)
                max = temp*(j-i);
            if(height[i]>height[j])
                j--;
            else
                i++;
        }
        return max;
    }
};

猜你喜欢

转载自blog.csdn.net/jaster_wisdom/article/details/79917525