11.盛水最多的容器
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例: |
---|
输入: [1,8,6,2,5,4,8,3,7] 输出: 49 |
果然还是我太菜,除了暴力法外,一直没想出怎样才能不漏掉最优解,直到在评论里看见了下面解释:
对O(n)的算法写一下自己的理解,一开始两个指针一个指向开头一个指向结尾,此时容器的底是最大的,接下来随着指针向内移动,会造成容器的底变小,在这种情况下想要让容器盛水变多,就只有在容器的高上下功夫。 那我们该如何决策哪个指针移动呢?我们能够发现不管是左指针向右移动一位,还是右指针向左移动一位,容器的底都是一样的,都比原来减少了 1。这种情况下我们想要让指针移动后的容器面积增大,就要使移动后的容器的高尽量大,所以我们选择指针所指的高较小的那个指针进行移动,这样我们就保留了容器较高的那条边,放弃了较小的那条边,以获得有更高的边的机会。
豁然开朗,一下问题就变简单了
class Solution {
public:
int maxArea(vector<int>& height) {
int max = 0, size, p1 = 0, p2 = height.size() - 1;
while(p1 < p2){
if(height[p1] <= height[p2])
size = (p2 - p1)*height[p1++];
else
size = (p2 - p1)*height[p2--];
max = max>size? max : size;
}
return max;
}
};
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.