0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

盛最多水的容器:双指针的经典题目

算法与数据结构 来源:吴师兄学算法 作者:吴师兄学算法 2022-07-28 11:25 次阅读

大家好,我是吴师兄,

今天的题目来源于 LeetCode 第 11 号问题:盛最多水的容器,难度为「中等」,属于双指针的经典题目

一、题目描述

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

二、题目解析

一开始,我们先去考虑相距最远的两个柱子所能容纳水的面积。

79f574dc-0e24-11ed-ba43-dac502259ad0.jpg

接下来去思考,我们去移动哪根柱子会更加合适?

这里我们需要注意一点:无论移动哪根柱子,柱子之间的宽度都是变小的

移动右边那根更高的柱子?

7a146cc0-0e24-11ed-ba43-dac502259ad0.jpg7a20b4a8-0e24-11ed-ba43-dac502259ad0.jpg

由于水面高度是由最短的柱子决定的,所以移动右边那根更高的柱子的时候,水面高度一定是不会增加,甚至有可能遇到更短的柱子而变小,而宽度有一定再减少,所以水的面积也一定减少

移动左边那根更短的柱子?

这时候,水的高度是不确定的,那么面积也是不确定的,有可能比之前更大,也有可能更小或者相等。

所以,我们可以得出一个结论:移动两根柱子之间更短的那根柱子,才有可能在宽度一定变小的情况下,找到一个更高的水面,从而使得面积有可能更大

那接下来这道题目的解法也就有了:

1、设置两个索引,分别指向容器的两侧,即索引left指向最左边的柱子,索引right指向最右边的柱子。

7a3639ea-0e24-11ed-ba43-dac502259ad0.jpg

2、记录下此时的水的面积,可以定义为 res

3、观察需要向内移动哪根柱子

  • 1)如果移动较高的柱子,由于水的宽度在变小,而水的高度一定不会增加,所以最终水的面积不会超过之前记录的水的面积 res
  • 2)所以,只能移动较短的柱子,然后计算此时水的面积,再与之前记录的水的面积 res 进行比较,保存那个更大的值

4、再去判断应该向内移动哪根柱子

5、直到leftright相遇为止

三、参考代码

1、Java 代码

//登录AlgoMooc官网获取更多算法图解
//https://www.algomooc.com/587.html
//作者:程序员吴师兄
//代码有看不懂的地方一定要私聊咨询吴师兄呀
//盛最多水的容器(LeetCode11):https://leetcode-cn.com/problems/container-with-most-water/
classSolution{
publicintmaxArea(int[]height){

//设置两个索引,分别指向容器的两侧

//索引left指向最左边的柱子
intleft=0;

//索引right指向最右边的柱子
intright=height.length-1;

//设置一个变量用来保存当下水的最大面积
intres=0;

//移动left和right,直到left和right相遇为止
while(left< right){

           //水的宽度是right-left
intwidth=right-left;

//水的高度由两根柱子最短的那根决定
inth=Math.min(height[left],height[right]);

//计算此时水的面积
intarea=width*h;

//如果此时水的面积大于了我们之前保存的那个值,我们需要更新一下
if(area>=res){
//更新res的值为area,确保res一直都是最大的值
res=area;
}

//接下来去观察需要移动哪根柱子:必定是最短的那根柱子

//如果左边的柱子更短,那么向内移动左边的柱子,因为只有这样,才有可能找到一个更高的水面
//在宽度一定变小的情况下,水的面积才有可能增大
if(height[left]< height[right]){
               //向内移动左边的柱子
left++;

//如果右边的柱子更短,那么向内移动右边的柱子,因为只有这样,才有可能找到一个更高的水面
//在宽度一定变小的情况下,水的面积才有可能增大
}else{
//向内移动右边的柱子
right--;
}

}

//最后返回最大的面积res即可
returnres;
}
}

2、C++ 代码

//登录AlgoMooc官网获取更多算法图解
//https://www.algomooc.com/587.html
//作者:程序员吴师兄
//代码有看不懂的地方一定要私聊咨询吴师兄呀
//盛最多水的容器(LeetCode11):https://leetcode-cn.com/problems/container-with-most-water/
classSolution{
public:
intmaxArea(vector<int>&height){
//设置两个索引,分别指向容器的两侧

//索引left指向最左边的柱子
intleft=0;

//索引right指向最右边的柱子
intright=height.size()-1;

//设置一个变量用来保存当下水的最大面积
intres=0;

//移动left和right,直到left和right相遇为止
while(left< right){

           //水的宽度是right-left
intwidth=right-left;

//水的高度由两根柱子最短的那根决定
inth=min(height[left],height[right]);

//计算此时水的面积
intarea=width*h;

//如果此时水的面积大于了我们之前保存的那个值,我们需要更新一下
if(area>=res){
//更新res的值为area,确保res一直都是最大的值
res=area;
}

//接下来去观察需要移动哪根柱子:必定是最短的那根柱子

//如果左边的柱子更短,那么向内移动左边的柱子,因为只有这样,才有可能找到一个更高的水面
//在宽度一定变小的情况下,水的面积才有可能增大
if(height[left]< height[right]){
               //向内移动左边的柱子
left++;

//如果右边的柱子更短,那么向内移动右边的柱子,因为只有这样,才有可能找到一个更高的水面
//在宽度一定变小的情况下,水的面积才有可能增大
}else{
//向内移动右边的柱子
right--;
}

}

//最后返回最大的面积res即可
returnres;
}
};

3、Python 代码

#登录AlgoMooc官网获取更多算法图解
#https://www.algomooc.com/587.html
#作者:程序员吴师兄
#代码有看不懂的地方一定要私聊咨询吴师兄呀
#盛最多水的容器(LeetCode11):https://leetcode-cn.com/problems/container-with-most-water/
classSolution:
defmaxArea(self,height:List[int])->int:
#设置两个索引,分别指向容器的两侧

#索引left指向最左边的柱子
left=0

#索引right指向最右边的柱子
right=len(height)-1

#设置一个变量用来保存当下水的最大面积
res=0

#移动left和right,直到left和right相遇为止
whileleft< right :

           #水的宽度是right-left
width=right-left

#水的高度由两根柱子最短的那根决定
h=min(height[left],height[right])

#计算此时水的面积
area=width*h

#如果此时水的面积大于了我们之前保存的那个值,我们需要更新一下
ifarea>=res:
#更新res的值为area,确保res一直都是最大的值
res=area

#接下来去观察需要移动哪根柱子:必定是最短的那根柱子

#如果左边的柱子更短,那么向内移动左边的柱子,因为只有这样,才有可能找到一个更高的水面
#在宽度一定变小的情况下,水的面积才有可能增大
ifheight[left]< height[right] :
               #向内移动左边的柱子
left+=1

#如果右边的柱子更短,那么向内移动右边的柱子,因为只有这样,才有可能找到一个更高的水面
#在宽度一定变小的情况下,水的面积才有可能增大
else:
#向内移动右边的柱子
right-=1

#最后返回最大的面积res即可
returnres

四、复杂度分析

时间复杂度:O(N),双指针总计最多遍历整个数组一次。

空间复杂度:O(1),只需要额外的常数级别的空间。

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2960

    浏览量

    104587
  • 容器
    +关注

    关注

    0

    文章

    494

    浏览量

    22050
  • 代码
    +关注

    关注

    30

    文章

    4761

    浏览量

    68405

原文标题:双指针,从两头开始内卷,先卷了挫的那头

文章出处:【微信号:TheAlgorithm,微信公众号:算法与数据结构】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    超级电容器的为什么电层间隔小

    超级电容器因其高功率密度、长循环寿命和快速充放电能力而在许多领域受到重视。这些特性主要归功于其独特的电层结构。 超级电容器的工作原理 电层的形成 : 当电极浸入电解质中时,电极表面
    的头像 发表于 09-27 10:29 326次阅读

    面试常考+1:函数指针指针函数、数组指针指针数组

    在嵌入式开发领域,函数指针指针函数、数组指针指针数组是一些非常重要但又容易混淆的概念。理解它们的特性和应用场景,对于提升嵌入式程序的效率和质量至关重要。一、
    的头像 发表于 08-10 08:11 748次阅读
    面试常考+1:函数<b class='flag-5'>指针</b>与<b class='flag-5'>指针</b>函数、数组<b class='flag-5'>指针</b>与<b class='flag-5'>指针</b>数组

    一面低压柜最多能放多少台电容器

    在电力系统中,低压柜是一个至关重要的设备,用于保护、控制和分配电力。而电容器则作为一种具有储能功能的电气元件,常用于提高系统的功率因数、稳定电压等方面。那么,一面低压柜最多能放多少台电容器呢? 一面
    的头像 发表于 07-04 14:26 514次阅读
    一面低压柜<b class='flag-5'>最多</b>能放多少台电<b class='flag-5'>容器</b>

    电层法拉电容器相较于传统化学电池有什么优点?

    电层法拉电容(DoubleLayerCapacitor)也被称为超级电容器(Supercapacitor)或超级电容(Ultracapacitor),是一种能量存储设备,用于存储和释放大量电荷
    的头像 发表于 06-28 11:35 412次阅读
    <b class='flag-5'>双</b>电层法拉电<b class='flag-5'>容器</b>相较于传统化学电池有什么优点?

    静电计和验电器的指针偏角和什么有关?

    静电计和验电器的指针偏角是由多种因素决定的,这些因素包括电容器的电容变化、电荷量、电势差、分布电容、静电计的显示特性曲线等。
    的头像 发表于 05-20 17:53 6693次阅读

    探寻未来科技:超亲聚合物超级电容器

    聚合物超电容,一种新型储能装置,以亲水性材料构筑电容器架构,具备高效率储能及快速充放电能力。相较于传统电池,亲聚合物超电容拥有更高能量密度以及更长使用寿命,堪称绿色能源存储的理想选择。
    的头像 发表于 04-12 11:49 414次阅读

    爆点十足!腾精密半导体技术矩阵亮相

    沪上展,爆点十足 3月20~22日,备受瞩目的 慕尼黑电子展、SEMICON展 正在火热开展中 Tensun腾与国内外展商 专业人士及媒体齐聚一堂 共襄展现场图▼ 腾
    的头像 发表于 03-21 08:43 379次阅读
    爆点十足!腾<b class='flag-5'>盛</b>精密半导体技术矩阵亮相<b class='flag-5'>双</b>展

    电层电容器的工作原理 电层电容器的特点

    电层电容器的工作原理 电层电容器的特点  电层电容器是一种特殊的电
    的头像 发表于 03-07 17:14 3952次阅读

    电层电容器的分类及优点

    电层电容器的分类及优点  电层电容器是一种能够存储电荷的电子设备,它由两个电极和介质组成,能够产生一个很大的表面积-电介质界面,从而实现高电容量。
    的头像 发表于 03-07 16:39 1004次阅读

    电层电容器和赝电容器的区别

    电层电容器和赝电容器的区别  电层电容器和赝电容器是目前广泛应用于能量存储领域的两类电
    的头像 发表于 03-05 15:48 2493次阅读

    C语言的指针用法

    C语言编程中善用指针可以简化一些任务的处理,而对于一些任务(比如动态内存分配),必须要有指针才行的。也就是说精通C指针编程是很有必要的,帮助你成为一名优秀的Cer。
    发表于 03-05 14:22 329次阅读
    C语言的<b class='flag-5'>指针</b>用法

    怎么理解指针指针

    怎么理解指针指针?其实这个概念并不难,只是把它放到实际应用中,容易造成困扰。
    的头像 发表于 02-23 16:46 1110次阅读
    怎么理解<b class='flag-5'>指针</b>的<b class='flag-5'>指针</b>?

    函数指针指针函数是不是一个东西?

    函数指针的本质是指针,就跟整型指针、字符指针一样,函数指针指向的是一个函数。
    的头像 发表于 01-03 16:35 507次阅读
    函数<b class='flag-5'>指针</b>和<b class='flag-5'>指针</b>函数是不是一个东西?

    数组和指针不相同吗?数组和指针有哪些区别

    数组就是指针指针就是数组,这样的言论在评论区看到不下于10次。
    的头像 发表于 12-13 16:34 1362次阅读
    数组和<b class='flag-5'>指针</b>不相同吗?数组和<b class='flag-5'>指针</b>有哪些区别

    数组与指针不能混用的情况

    数组与指针不能混用的情况  数组与指针是 C/C++ 中非常常见的特性和概念。然而,在某些情况下,数组与指针是不能混用的。这种情况通常涉及到数组的内存分配和数组的块拷贝。 首先,让我们回顾一下数组
    的头像 发表于 12-07 13:46 580次阅读