一、题目描述
原题连接:https://leetcode.cn/problems/container-with-most-water/
题目描述:
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:输入:height = [1,1]
输出:1
二、解题
c语言获得最小值和最大值的方法:
- 用三目操作符a<=b?a;b或者a>b?a:b;
- 也可以利用宏#define Max(a,b) a>b?a:b; #define Min(a,b) a<=b?a:b;这样方便一点
- 最方便的当然还是直接调用库函数fmin,fmax函数啦!
方法1:暴力两层for循环
思路分析:定义左右边界left和right,都初始化为0,然后就是和冒泡排序的思路一样,将所有可能取值都遍历一边,遍历的同时不断更新面积最大值。
由于冒泡排序大家都很熟悉啦,这里就不赘述了,直接上代码。而且这种暴力解法会超时,也不符合堂堂中等题的解法。
int maxArea1(int* height, int heightSize) {
assert(height);
int i = 0;
int j = 0;
int max_area = 0; // 保存最大的容器容量
for (i = 0; i < heightSize - 1; i++) {
for (j = i + 1; j < heightSize; j++) {
int short_plank = 0; // 每次枚举到的容器的短板
int area = 0; // 每次枚举到的容器的容量
short_plank = height[i] < height[j] ? height[i] : height[j];
area = short_plank * (j - i);
if (area > max_area) {
max_area = area;
}
}
}
return max_area;
}
时间复杂度:O(N^2)
空间复杂度:O(1)
方法2:经典双指针
思路分析:这道题的解决方法又是经典的双指针。我们定义left和right指向数组的两端,首先我们要明确面积等于长乘高(S=LxH),H是fmin(heigh[left],heigh[right]),L是right-left。
而我们在找面积的最大值的过程中,长肯定是减小的,所以希望就寄托在高上了。
为了让高越来越高,我们每次更新左右边界的过程中就要抛弃较小的那个边,这样高就会越来越高啦,面积也就会越来越大了,直到left=right的时候,返回最大的面积即可。
有了思路,代码写起来就行云流水啦!
代码实现
int maxArea(int* height, int heightSize){
int left=0,right=heightSize-1,max=0;
while(left<right)
{
//获得本次面积
int area = fmin(height[left], height[right]) * (right - left)
//更新最大面积
area= area> max ? area : max;
//左边边界较小,移动左边. 右边界较小,移动右边
if(height[left] < height[right]) left++;
else right--;
}
return max;
}
时间复杂度:O(N)
空间复杂度:O(1)
三、总结
本题又是一道很经典的双指针问题,不过是从两端开始的双指针,也是很常见的,希望大家能有所收获。
再你感觉已经完全了解双指针的时候,不妨再来道题练练手,检验检验?
此题和本题做法很相像,希望大家可以举一反三,毕竟只有自己敲出来的才是自己的!
本次刷题分享到此结束,希望大家多多点赞浏览支持啦!