willluckysmile 2020-04-26
给你 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
思路:使用双指针,开始指向左右边界。每次将对应的数字较小的那个指针往另一个指针的方向移动一个位置,表示我们认为这个指针不可能再作为容器的边界了。并检查是否要更新面积最大值,直到两个指针指向同一个位置。
为什么每次都移动对应数字小的那一个指针?
假设当前左指针和右指针指向的数分别为 x和 y,不失一般性,我们假设x≤y。同时,两个指针之间的距离为 t。那么,它们组成的容器的容量为:
min(x, y) * t = x * t
我们可以断定,如果我们保持左指针的位置不变,那么无论右指针往左怎么移动,这个容器的容量都不会超过 x * t了。
class Solution { public: int maxArea(vector<int>& height) { int l = 0, r = height.size() - 1; int ans = 0; while (l < r) { int area = min(height[l], height[r]) * (r - l); ans = max(ans, area); if (height[l] <= height[r]) { ++l; } else { --r; } } return ans; } };
这是第一次遇到这个问题时的自己的做法,记录一下
class Solution { public: int maxArea(vector<int>& height) { int n=height.size(); if(n<2) return 0; int left(0),right(n-1),maxarea(0);int minh; int leftTaller=0; int rightTaller=0; for(;left<n;left++) { if(height[left]>leftTaller)//如果不大于,不用进行计算比较更新maxarea,因为根本不肯大于maxarea { leftTaller=height[left]; minh=height[left]<height[right]?height[left]:height[right]; maxarea=maxarea>(minh*(right-left))?maxarea:(minh*(right-left)); right--; while(right>left) { if(height[right]>rightTaller)//只有大于才要检查是否要更新maxarea { rightTaller=height[right]; minh=height[left]<height[right]?height[left]:height[right]; maxarea=maxarea>(minh*(right-left))?maxarea:(minh*(right-left)); } right--; } right=n-1; rightTaller=height[right]; } } return maxarea; } };