题目介绍及描述
上一篇文章我们讲解了第四题,也就是数组中的第二题:寻找两个有序数组的中位数
这篇文章介绍一下第11题,也就是数组中的第三道题,盛最多水的容器。这道题难度标记为中等,我们先来看一下题目:
题目分析
我们对这个题做一个大体的分析。所谓盛最多的水,其实就是让我们在这些长方形的柱子中找出两个柱子,让他们围成的面积是最大的。有很多同学可能刚上来的时候就想着,那只要底或者高最长就好了。其实这只是一种特殊的情况,我们还是要通过计算每一个围成的面积,从而比较大小。
但是这种暴力求法实在不太提倡,空间复杂度和时间复杂度都不会特别乐观,在这里提供一个简单易懂的方法:双指针法。
由上图所示:在第一个长方形柱子(左指针left)和最后一个长方形柱子(右指针right)两个位置设置两个指针,这两个指针将相向而行,共同向中间行走。
我们的条件设置为:
1.如果左指针left指向的长方形柱子比右指针right指向的长方形柱子矮,就将左指针left进行+1操作
2.如果右指针right指向的长方形柱子比左指针left指向的长方形柱子矮或一样高(这里无所谓的,一样高的时候哪个指针移动都可以),就将右指针right进行-1操作。
每次计算完围成矩形的面积后,要保存结果以便和下一个比较,把大的面积重新赋值给当前结果。
res = max(res,新算的面积)
#这里的面积通过长*高计算,高就是数组中对应的矩形高度
#长度就是两个指针之间的差,即right-left
代码实现
其实思路很简单也很清晰,知道了思路代码就非常好写了,下面来看一下代码实现:
python版本:
class Solution:
def maxArea(self, height):
left, right, res = 0, len(height) - 1, 0
while left < right:
if height[left] < height[right]:
res = max(res, height[left] * (right - left))
left += 1
else:
res = max(res, height[right] * (right - left))
right -= 1
return res
C++版本:
class Solution {
public:
int max(int a,int b)
{
if(a > b)
return a;
else
return b;
}
int maxArea(vector<int>& height) {
//初始化
int left = 0;
int right = height.size() - 1;
int res = 0;
while(left < right)
{
if(height[left] < height[right])
{
res = max(res,height[left] * (right - left));
left += 1;
}
else
{
res = max(res,height[right] * (right - left));
right -= 1;
}
}
return res;
}
总结
这道题用暴力法解题虽然很简单,但是并不是题目的本意,本意是让我们掌握双指针法,通过两个指针所指的不同矩形柱子来计算围成的面积,这样比暴力法更加快速的解决问题,时间复杂度也从暴力法的O(n^2)降到了O(n)。空间复杂度两种方法都是O(1).
像这种可以从两边像中间靠拢并且最后趋于相同位置的题目,都可以想到使用双指针操作。最近做了挺多数组的题目,发现后面的题目也大多都是用双指针法或者二分法,所以这两种方法希望大家掌握。
该方法所用的时间及内存消耗如下:
python版本:
C++版本:
这道题到这里我们就分析完了,下一篇是第十五题——三数之和。
最后,中国加油!武汉加油!