作者 : XiaXinyu
日期 :2021-10-01
题目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CbhY4xrk-1633062394515)(https://z3.ax1x.com/2021/10/01/4T7Jun.md.png)]
理解
这道题的关键点在于要理解木桶效应,即一个木桶能装多少水取决于最短的木板长度
题解一(双指针)
经过思考可以得出两个解题的关键点
- 1.相同情况下,左右边界的距离越远越好
- 2.面积受限于左右边界中较短边界
下面对关键点1进行证明
证明关键点1:
因为计算容量的公式为area = (min(al,ar) * (r - l))即左右边界中的较短边乘以左右边界的距离
所以当al = ar 的时候r 和 l之间的距离越大所计算出的面积越大
证毕
根据两个关键点可以得出这道题的思路,初始化两个指针分别指向数组的左右两端
重点在于采用哪种策略移动指针
应该移动数字较小的指针还是数字较大的指针呢?
答案是较小的,下面来证明这种做法是正确的
证明:
首先令初始状态左右指针指向的数分别x,y,假设x <= y,左右指针之间的距离为t
那么它们组成容器的容量为 area = min(x,y) * t = x * t
先看看移动右指针(指向数字较大的指针
)的情况,因为右指针一定会向左移动到某个位置,所以t一定减小,假设移动后右指针指向的数为y1,左右指针边界为t1,则此时的y1有两种情况
-
1.y1 <= y 则 min(x,y1) <= min(x,y)
-
2.y1 > y 则min(x,y1) = min(x,y) = x
综上:min(x,y1) <= min(x,y) = x,而t1 < t所以无论右指针向左移动到哪个位置,容器的容量area = min(x,y1) * t1一定会减小,所以我们只能移动左指针即指向数字较小的指针来得到更大的容量
证毕
还有一种特殊情况就是左右指针指向的数字相等时应该移动哪个指针,其实这种情况移动哪个指针都是一样的,仍然有两种情况需要讨论一下
-
1.如果左右指针之间的数字只有一个或者没有大于左右指针指向的数字,那么无论移动哪个指针答案都是左右指针当前指向的数字所计算出的容量,所以移动谁都一样
-
2.如果左右指针之间的数字有两个或者以上大于左右指针指向的数字,此时下图中1号和8号之间有两个更大的数字,假设先移动左指针,那么1号会变成4号,在这个过程中一定不会产生更大的容量,因为2,3号数字都小于7号,然后右指针会变为6号,因为在移动过程中的数字都不会大于1号和8号,所以先移动谁是一样的。
代码
public class Solution{
public int maxArea(int[] height){
int l = 0, r = height.length - 1;
int ans = 0;
while(l < r){
ans = Math.max(Math.min(height[l],height[r]) * (r - l), ans);
if(height[l] <= height[r])
l ++;
else
r --;
}
return ans;
}
}
时间复杂度
:O(n) n为数组的长度
空间复杂度
:O(1)