盛最多水的容器
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
暴力法
- 固定 l e f t = [ 0 , h e i g h t S i z e − 1 ] left=[0,heightSize-1] left=[0,heightSize−1],寻找right,使得 h e i g h t [ r i g h t ] ∗ ( r i g h t − l e f t ) height[right]*(right-left) height[right]∗(right−left)或 h e i g h t [ l e f t ] ∗ ( r i g h t − l e f t ) height[left]*(right-left) height[left]∗(right−left)最大。时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( 1 ) O(1) O(1)。
- 代码如下
int maxArea(int* height, int heightSize){
int max_warter=0;
for(int left=0;left<heightSize;left++){
for(int right=left+1;right<heightSize;right++){
if(height[left]<height[right]){
max_warter=max(max_warter,height[left]*(right-left));
}else
max_warter=max(max_warter,height[right]*(right-left));
}
}
return max_warter;
}
贪心法
- 一个区间能够容纳水的面积=区间长度*min(左端点高度,右端点高度)
- 如果min(左端点高度,右端点高度)相同则区间长度越大,能够容纳的水越多。如果区间长度相同,则min(左端点高度,右端点高度)越大,能够容纳的水越多。
- 如果想让面积最大则要么增加区间长度,要么使得min(左端点高度,右端点高度)增大。
- 如果从最长区间开始依次缩小区间,而每次要缩小区间时,选择留下高度最高的端点,才有可能使得装的水大于当前能够容纳的水容量(舍去的区间的能够容纳的水一定比选择的区间容纳的水更少,因为min(左端点高度,右端点高度)相同,但区间长度要小于当前区间)。
- 每次缩小区间要更新当前能够容纳水的最大面积
max_warter=max(max_warter,(right-left)*min(height[left],height[right]));
- 时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)。
- 代码如下
int maxArea(int* height, int heightSize){
int left=0,right=heightSize-1;
int max_warter=0;
while(left<right){
max_warter=max(max_warter,(right-left)*min(height[left],height[right]));
if(height[left]>height[right]){
right--;
}else{
left++;
}
}
return max_warter;
}