Leetcode 011 - 盛更多水的容器
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
首先,通过理解题目,我们可以知道,垂线 i i i 和垂线 j j j 构成的容器,可以容纳的水量为 m i n ( a i , a j ) × ( j − i ) min(a_i, a_j) \times (j-i) min(ai,aj)×(j−i) 。于是题目转变为:
r e s = max i , j = 0 i , j = n m i n ( a i , a j ) × ( j − i ) res = \max \limits_{i,j=0}^{i,j=n} min(a_i, a_j) \times (j-i) res=i,j=0maxi,j=nmin(ai,aj)×(j−i)
很显然,通过枚举 i i i, j j j 可以得到本题的答案。但这是比较笨的方法。
仔细观察上式,我们可以通过枚举 j − i j-i j−i 并结合贪心思想得到最大的 m i n ( a i , a j ) min(a_i, a_j) min(ai,aj) 获得我们想要的答案。
初始时设置 i = 0 , j = n − 1 i=0,j=n-1 i=0,j=n−1 ,此时, j − i j-i j−i 最大,计算当前容积;而遍历 j − i j-i j−i 无非两种方式,要么右移 i i i ,要么左移 j j j 。我们假设 a i < a j a_i<a_j ai<aj ,那么若 i i i 不变化,无论如何减小 j j j 都无法获得更大的面积值;因此,借助贪心的思想,此处只能选择移动 a k a_k ak 较大的一个指针。
如此循环,直至 i , j i,j i,j 相遇,能得到的最大容积即为本题的答案
AC版本代码如下:
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0, right = len - 1;
int maxArea = min(height[left], height[right]) * (right - left);
while(left < right){
int curArea = min(height[left], height[right]) * (right - left);
if(maxArea < curArea) maxArea = curArea;
if(height[left] <= height[right])
left++;
else
right--;
}
return maxArea;
}
};