leetcode_11 盛最多水的容器
1. 题意
直接复制过来。
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
其实就是给定一个数组heightheightheight,
我们令w(i,j)w(i,j)w(i,j)表示容器以iii为左端点,以jjj为右端点时能装多少水。
即
w(i,j)=min(height[i],height[j])×(j−i)w(i,j) =\min(height[i],height[j])\times(j-i) w(i,j)=min(height[i],height[j])×(j−i)
最终的目标相当于
max{w(i,j)},0≤i<j<height.size()\max \left\{ w(i,j)\right\},\quad 0 \le i <j <height.size() max{w(i,j)},0≤i<j<height.size()
2. 题解
2.1 暴力
直接枚举左右端点的位置,时间复杂度O(n2)O(n^2)O(n2)。
这里的枚举是固定左,枚举右。
class Solution {
public:int maxArea(vector<int>& height) {int n = height.size();int ans = 0;for (int i = 0; i < n - 1;i++) {for (int j = i + 1; j < n; ++j) {int water = (j - i) * min(height[j], height[i]);ans = max(ans, water);}}return ans;}
};
2.2 单调数组
其实这里也还是枚举,只不过是固定右端点,枚举左端点。
假设我们枚举的右端点此时为jjj,那么我们需要jjj之前的所有端点吗?
不!比如说i<k<ji < k <ji<k<j且height[i]≥height[k]height[i] \ge height[k]height[i]≥height[k],我们很容易就能得到
w(i,j)>w(k,j)w(i,j) >w(k,j)w(i,j)>w(k,j),说明这个kkk我们不需要加入到左端点的列表中去了。
也就是说对于左端点列表来说,它必然是单调递增的。
再通俗一点就是,靠近左边的元素它先跑,后面的元素要想赶得上必然
速度要比前面的快才有可能超过前面的元素。
时间复杂度还是O(n2)O(n^2)O(n2)
class Solution {
public:int maxArea(vector<int>& height) {int n = height.size();int ans = 0;vector<int> inc;inc.push_back(0);int cnt = 1;for (int i = 1; i < n;i++) {for (int j = 0;j < cnt; ++j) {ans = max(ans, min(height[i], height[inc[j]]) * (i - inc[j]) );}if (height[i] > *inc.rbegin()) {inc.push_back(i);++cnt;}}return ans;}
};
2.3 双指针+贪心
先说下思路,左右相向双指针,哪边小哪边就往中间移动。
这个思路反正我是想不到的,大概只有做过的人知道吧!
还是证明下这个策略的正确性。
我们假设此时左指针为iii,
右指针为jjj,且i<j,height[i]>height[j]i<j, height[i]>height[j]i<j,height[i]>height[j]。
按照上面的策略,我们知道需要将右指针jjj往左移,
此时我们考虑我们并没有实际计算的部分,
也就是w(k,j),i<k<jw(k,j), i<k<jw(k,j),i<k<j。
w(k,j)w(k,j)w(k,j)的值有没有可能才是我们的最大值呢 ?
实际上是不可能的!
因为w(k,j)≤height[j]×(j−k)<height[j]×(j−i)=w(i,j)w(k,j)\le height[j] \times(j-k)<height[j]\times(j-i)=w(i,j)w(k,j)≤height[j]×(j−k)<height[j]×(j−i)=w(i,j)。
对于height[i]<height[j]height[i]<height[j]height[i]<height[j]的情况同理。
综上,所以说这种策略是正确的!
下面来看无人在意的代码部分
class Solution {
public:int maxArea(vector<int>& height) {int n = height.size();int i = 0;int j = n - 1;int ans = 0;while (i < j) {ans = max( ans, min(height[i], height[j]) * (j - i) );if (height[i] < height[j])i++;elsej--;}return ans;}
};
3. 参考
krahets