力扣Hot100题带刷--11.盛最多水的容器(你还在写两层for循环吗?)

一,题意分析 如何找到最大容积
最大容积就是要保证长乘宽(这里的height)最大,我们很容易就想到两层for循环,在第二层循环里面,每一次循环记录一下当前的容积,并且和目前的最大容积进行比较,每次循环看是否要更新最大容积max_weight,就结束了,也就是方法一。
二,方法一 非常淳朴的两层for循环(但超时)
class Solution {
public:
int maxArea(vector<int>& height) {
int n=height.size();
int max_weight=0;//变量记录最大容量
int h=0;//选择谁作为容器的高
int weight=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
h=min(height[i],height[j]);
weight=h*(j-i);
max_weight=max(weight,max_weight);
}
}
return max_weight;
}
};
三,方法二 双指针法的引入
双指针的优点:1.降低时间复杂度,2.减少不必要的操作,3.原地操作节省空间,4.逻辑清晰。这个题目体现了1 2 4 三点。第3个优点,大家可以看Hot100的另一题283. 移动零 - 力扣(LeetCode)。
由于双指针法没有固定的套路或者说是模版,需要大家在不断解决不同问题时候增加熟练度,最后也能使用的和用for循环嵌套一样熟练。
引入双指针后,通常情况下,在每一次循环执行了当前循环操作后,两个左右指针不断向着中间靠,最后两者相等的时候跳出循环。时间复杂度巧妙地缩短到了O(n)。
在我看来,使用好双指针法的关键在于能否在读完题后,对两个指针为了解决最终问题而具有的实际意义,自己要有一个清晰准确的把握。
class Solution {
public:
int maxArea(vector<int>& height) {
int l=0,r=height.size()-1;
int ans=0;
while(l<r){
int area=min(height[r],height[l])*(r-l);
ans=max(ans,area);
if(height[l]<=height[r]){
l++;
}else{
r--;
}
}
return ans;
}
};
我们这题里面的左右指针就是为了找到能围成更大容积的两条垂线组合—— 左指针从数组起始端出发,右指针从数组末端出发,二者界定的区域就是当前待计算容积的容器边界。
一言以蔽之:我们 left++ 和 right-- 都是为了尝试取到更多的水,如果短的板不动的话,取到的水永远不会比上次多。因为容器的容积由 “短板高度” 和 “两板间距” 共同决定,当短板固定时,无论移动长板还是保持不动,间距只会减小或不变,而高度始终受限于短板,容积必然不会增大。只有移动短板,才有可能遇到更高的板,让新的短板高度提升,从而为容积增大创造可能 。
四,最后的话
这些只是我不太成熟,不太完善的一些思考,随着后续的学习,我也会不断完善自己的语言和代码能力,持续更新,希望帮助到大家,谢谢!(能给煮波点个赞就更好了,哈哈)
更多推荐

所有评论(0)