LeetCode 热题 HOT 100 第7天: “盛最多水的容器”

leetcode hot100 中等难度 day03-刷 阅读详情

继续刷LeetCode 热题 HOT 100 的题目,并且在博客更新我的solutions。在csdn博客中我会尽量用文字解释清楚,相关Java代码大家可以前往我的个人博客jinhuaiyu.com中查看。
做题不是为了做这道题,而是为了提取思想解决其他问题。今天的题目用到的思想和前几天都不一样,因此有必要深刻理解加深记忆。
题目:盛最多水的容器
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 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
示例 3:
输入:height = [4,3,2,1,4]
输出:16
示例 4:
输入:height = [1,2,1]
输出:2
提示:
n == height.length
2 <= n <= 105
0 <= height[i] <= 104
solution: 缩减搜索空间(双指针)
作为一道中级难度算法题,看似简单的肯定不是用暴力破解,实际上,分治法、动态规划在这里也用不上或者不是优解。双指针可能大家很容易就想到了,但是这道题需要被提炼的精髓在于缩减搜索空间
显而易见,如果讨论每一种可能,复杂度是O(n²),外面要思考有没有一些搜索空间是没有必要被讨论的,也就是在搜索过程中可以被直接跳过。官方给出的结题讲解不够清晰,虽然大家也能理解,但是没有直观体现出缩减搜索空间的魅力。首先,我还是要先简单讲一下解题方法,最后给出解空间被缩减的直观图解。
面积(装水容积)取决于左右两条边的长度,准确地说,取决于其中的短边。我们的双指针从最左右两侧开始移动来讨论,同时用一个变量max记住每个过程中最大的面积。刚开始时,假设左右两侧分别为a和b(a>b,哪个大不影响讨论)长,如果以这两天边为容器左右两边,则面积为b乘以中间的距离d,设为s。如果左侧(长的一侧)往内移动,由于d在变短,而不管此时移到的边有多高,算面积时,高都不能超过b(面积取决于短边)。因此我们可以发现,以最右侧为一条边,其他的情况都不必再讨论了(反正不可能超过s)。
于是搜索空间被缩减了,这些不讨论的相当于把最右侧短边b去除,右指针往内移动一位,讨论此时左右指针内的子情况,当然,如果被除去的b边真的是最终结果的其中一边,那么一定是和最右侧a边构成最大面积,这个结果会在变量max中被更新,不会丢失。
剩下的子情况同理处理,每次更新max后除去当前左右指针中较短的那一条边,便可一次性省去一批情况不用讨论。
显然,最后的时间复杂度为左右指针每轮移动一位直到相遇的n次循环。下面给出搜索空间被缩减的直观图解:
假设有8条边,左右指针为i、j,由于i、j的约束条件的限制,搜索空间是白色的倒三角部分。可以看到,搜索空间的大小是 O(n²)数量级的。
在这里插入图片描述
要想得到 O(n)的解法,我们就需要能够一次排除多个单元格。假设左边的 0号边较短。根据刚才的推理,0号边目前的水面高度已经到了上限。由于 7号边已经是离0 号最远的了,如果换其他的边和 0号边配对,水的宽度只会更小,高度也不会增加,容纳水的面积只会更小。也就是说,0号边和 6, 5, …, 1号边的配对都可以排除掉了。记录了 (0,7) 这组边的结果之后,就可以排除 0号柱子了。这相当于 i=0 的情况全部被排除。对应于双指针解法的代码,就是 i++;对应于搜索空间,就是削减了一行的搜索空间,如下图所示。
在这里插入图片描述
排除掉了搜索空间中的一行之后,我们再看剩余的搜索空间,仍然是倒三角形状。我们检查右上方的单元格 (1, 7),即考虑 1 号边和 7号边,计算它们之间容纳水的面积。然后,比较两条边。
假设此时 7 号边较短。同理,7 号边已经是离1 号最远的了,如果换其他的边和 1号配对,水的宽度变小,高度也不会增加,容纳水的面积只会更小。也就是说,7号边和 2,3,…,6 号边的配对都可以排除掉了。记录了(1,7) 这组边的结果之后,就可以排除 7 号了。这相当于 j=7 的情况全部被排除。对应于双指针解法的代码,就是 j–;对应于搜索空间,就是削减了一列的搜索空间,如下图所示。在这里插入图片描述
可以看到,无论 i 和 j哪条边更长,我们都可以排除掉一行或者一列的搜索空间。经过 n步以后,就能排除所有的搜索空间,检查完所有的可能性。
最后,说明一下如果当前比较的两条边一样长,那么随便排除一条即可,因为如果是以这两条边中一条为最终结果,那最终结果的两条边一定是这两条一样长的边,这个结果会更新max,如果真的大会被记录下来不会丢失。随便移动的话,也不会影响最终结果max。如果两条边都不是最终结果的边,那么两条边迟早都被排除,哪个前哪个后也不影响。

Finally,带有详细注释的代码放在放在我的个人博客http://jinhuaiyu.com/leetcode-container-with-most-water/
希望后面碰到类似的题能想起今天的思想——缩减搜索空间。

Leetcode C++《 Hot 100-25》11.最多容器 Leetcode C++《 Hot 100-25》11.最多容器 切忌急躁,理解至上;循序渐进,接近最优 目 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 给定 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其... 阅读详情

相关推荐

笔试面试目:最多容器

周末,来看G公司的一道面试: 求max{|i-j|*min{a[i], a[j]}}的值,其中a是正整数数组,i和j的区间为[0, n-1]. 这其实就是leetcode中的“最多容器”,如下: 鲁迅说:暴力可以解决一切问题。 胡适说:暴力能解决的问题,都不是问题。 因为i和j的可能性是有限组合,所以暴力算法能得到结果,但无法通过面试。 用...

认知 行动 坚持 4854

leetcode力扣最多容器-最大容器问题

leetcode最多容器-最大容器问题如下 问题分析:此就是,有哪两条边围成的容器,可以更多的。这里的边即是上图中的每根柱子,也就是数组中元素对应的值,所以容器的高取决于较低的那个柱子,因为若没过会从上流出,容器的宽度取决于两根柱子之间的长度。 故问题可简化为求数组中 Min(a[i],a[j]) × | i-j | 的最大值; a[i],a[j]为上图中i,j任意两点的对应的柱子; 解决思路: 我们可以看到上诉图或者公式中,容器的高度取决于较低的那个柱子,当我们选择一个最低的柱子i = 0

qq_45308101的博客 1065

javaleetcode记录+简单思路(hot100+剑指offer 简单\中等难度)

避免重复刷每次都两眼一抹黑咩都不记得,简单记一下思路。 1. 两数之和(简单) 2. 两数相加(中等) 3. 无重复字符的最长子串(中等) 4. 寻找两个正序数组的中位数(困难) 5. 最长回文子串(中等) 10. 正则表达式匹配(困难) 11. 最多容器(中等) 15. 三数之和(中等) 17. 电话号码的字母组合(中等) 19. 删除链表的倒数第 N 个结点(中等) ...

昂萨哈凯尔可真难记啊 1701

LeetCode(CPP):一月刷完100(5)

33.搜索旋转排序数组(mid) 思路: 由于输入的数组部分有序,可以采用二分查找法; 首先要判断数组中是否有足够判断的元素个数,如果数组无元素,返回-1;只有一个元素则比较是不是target; 二分查找:因为是部分有序,要判断target是否在这个区域里,左侧用nums[0] <= target && target < nums[mid],右侧用nums[mid] < target && target <= nums[n - 1]。找不到

Breathmetoyou的博客 404

刷完 LeetCode 是什么平?能拿到什么平的 offer?

链接:https://www.zhihu.com/question/32019460编辑:深度学习与计算机视觉声明:仅做学术分享,侵删刷是我们一贯的学习方式,但是学霸和学渣的区别就在于...

深度学习与计算机视觉 3395

LeetCode HOT 100 解(仅记录解思路)

由于数组中只有一个元素出现一次,其余元素都出现两次,因此用集合中的元素之和的两倍减去数组中的元素之和,剩下的数就是数组中只出现一次的数字。遍历数组中的每个数字,如果集合中没有该数字,则将该数字加入集合,如果集合中已经有该数字,则将该数字从集合中删除,最后剩下的数字就是只出现一次的数字。指针p1在头结点处,指针p2在头结点的next处,然后p1每次移动1格,p2则走2步,若在其中一个进入null之前两者指向同一结点,则代表有环。使用双指针,左指针指向当前已经处理好的序列的尾部,右指针指向待处理序列的头部。

a131529的博客 9884

力扣HOT100合集

对于当前考虑的元素 nums[i],如果 dp[ j - nums[ i ] ] 为 true,说明可以用前面的元素构成和为 j -nums[ i ] 的子集,那么在加上当前元素 nums[ i ] 的情况下,就可以构成和为 j 的子集,因此 dp[ j ] 更新为 true。这样left往回走会导致错误的结果。最终得到的结果为[[1, 2, 3], [2, 1, 3], [3, 1, 2], [1, 3, 2], [2, 3, 1], [3, 2, 1]],即给定数组[1, 2, 3]的全排列结果。

qq_61504864的博客 5573

【力扣hot100】python刷笔记之双指针

给定一个数组 nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。,必须在不复制数组的情况下原地对数组进行操作。

qq_50927224的博客 2039

力扣(leetcodehot 100双指针看这一篇就够了

这里是阳明Coding,给大家分享一下力扣hot100里面关于双指针的目的一些解决方法及思路。如果有其他想法或者思路。我也会顺嘴提一下。

yyyCode的博客 1506

力扣-hot100最多容器-双指针)

补充: 这样做会不会漏掉,这里漏掉的情况只可能有一种,就是当两个高相等时,移动了随机一根,但是要明确的是高的长度是由最短的那根确定下来的,即便你后面有很长的,也会被这两根相同的限制,所以不论移动哪根都是一样的。解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。容器的长是由两直线(宽)的距离决定的,容器的高是两直线中最短的那根确定的。实事上并不是每条边(高)都是有价值的,宽的价值是很好确定的,最两侧的边,为宽的最大权重。// 容器的长是由两直线的距离决定的,容器的高是两直线中最短的那根。

A_long_way_to_go的博客 1066

hot100-最多容器(day5)

最多问题要求从整数数组中选择两条线段,与x轴构成能最多容器。暴力解法枚举所有组合,时间复杂度O(n²)会超时。优化思路采用双指针法:初始左右指针位于数组两端,每次移动较短的线段指针(因为移动较长指针必然减少量),计算当前量并更新最大值。

silver-kite的博客 1107

leetcodeHOT100汇总——java解已完结撒花

为了学习本文捋顺leetcodeHOT100的汇总 方便自己秋招刷 仅作刷笔记使用 感兴趣的小伙伴点一个赞吧。

qq_41810415的博客 9212

力扣hot100——双指针系列(移动零、最多容器、三数之和、接雨

力扣hot100——双指针系列(移动零、最多容器、三数之和、接雨

qq_63955073的博客 1185

LeetCode HOT100笔记(一):哈希表, 双指针

ps:笔记和代码按本人理解整理,重思路

学习记录 1675

Leetcode_hot_100 t5最多容器11

给定一个长度为n的整数数组height。有n条垂线,第i条线的两个端点是(i, 0)和。找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多。返回容器可以储存的最大量。你不能倾斜容器。49图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳(表示为蓝色部分)的最大值为 49。1法一(暴力解)对于每个左边界,遍历它右边的右边界,找到最大值,当然这种方法在数据量很大的时候通过不了Max_V = 0。

m0_74329301的博客 1026

力扣Hot100系列2(Java)——[双指针]总结(移动0,最多容器,三数之和,接雨

本文总结了力扣Hot100中关于双指针的四道典型目,重点分析了移动零和容器两个问题。对于移动零问题,通过左右指针交换非零元素实现原地操作,保持元素顺序;容器问题则利用双指针从两端向中间移动,通过比较高度计算最大容量。两种解法都体现了双指针在数组操作中的高效性,时间复杂度均为O(n)。文章通过具体示例逐步拆解算法执行过程,帮助理解指针移动策略和关键计算步骤。

2402_89049045的博客 1333

LeetCode Hot100(5/100)——11. 最多容器

双指针法以线性时间复杂度 O(n)找到最优解,是此的经典最佳方案。核心是通过移动较短边来可能获得更高的容器。理解“面积由短边决定”的原理,是解决此类问题的关键。

TracyCoder的博客 1087

LeetCode HOT 100 Java解——11. 最多容器

LeetCode HOT 100 Java解11. 最多容器双指针复杂度分析 11. 最多容器 目: 给你 nnn 个非负整数 a1,a2,...,ana_1,a_2,...,a_na1​,a2​,...,an​,每个数代表坐标中的一个点 (i, ai)(i, a_i)(i, ai​) 。在坐标内画 nnn 条垂直线,垂直线 iii 的两个端点分别为 (i, ai)(i, a_i)(i, ai​)

qq_20067165的博客 468
上一篇: LeetCode 热题 HOT 100 第6天: “正则表达式匹配”
下一篇: LeetCode 热题 HOT 100 第8天: “三数之和”
ultimate小锦
博客等级 码龄9年 23粉丝 · 66原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值