[算法学习02]相向双指针之盛最多水的容器

前言

盛最多水的容器 接雨水_哔哩哔哩_bilibili 灵茶山艾府大佬牛!

还是双指针,用法是上一讲的扩展,接雨水难度爆炸。

上一节的双指针偏套路,而这节的话思路非常重要。


提示:以下是本篇文章正文内容,下面案例可供参考

一、Leetcode11. 盛最多水的容器

给定一个长度为 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

解题思路 题目说找两根线,第i根线的长度就是heigh[i],然后求两根线围起来的长方形的最大面积。  那么这个长方形的宽就是 min(height[i],height[j]) ,长方形的长就是 j - i。

长方形的长就是 j - i,这个事是从图上看出来的,假设这个长方形取第一根线和最后一根线,可以发现长方形的长度是 9 - 1。 

先用暴力试了一下,61个样例过了50,过不去。

法1:暴力法

就是取一根线然后依次和第二根线、第三根。。。组合求面积,如果面积大了,就更新。

class Solution:
    def maxArea(self, height: List[int]) -> int:
        maxarea = 0
        for i in range(len(height) - 1):
            x = height[i]
            for j in range(i+1, len(height)):
                y = height[j]
                maxarea = max(maxarea, min(x, y)*(j - i))
        return maxarea

法2:双指针法 

这里是一个很巧妙的做法,之前我的想法是应用双指针必须对数组进行排序,其实不然。

当我们枚举两个端点的数值的时候,我们取到了最大的长(right - left)! 但是我们的宽呢,是两个线长中较小的那一段min(height[left], height[right])。其实就可以把较小的那根线排除了,因为接下来不管怎么枚举,我们的长度肯定是缩减的(right - left),但是高度又不可能高过较小线的高度,因此排除较小的线。接下来的高度就有可能高过之前的高度。

class Solution:
    def maxArea(self, height: List[int]) -> int:
        n = len(height)
        left = 0
        right = n - 1
        maxarea = 0
        while left < right:
            maxarea = max(maxarea, (right-left)*min(height[left], height[right]))
            if height[left] < height[right]:
                left = left + 1
            else:
                right = right - 1 
        return maxarea 

二、Leetcode42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

解题思路 这题我自己完全想不出,只能听课,看了两遍才看懂。

法1: 前后缀的方法

想象每个位置都有一个水桶,那么这个水桶的容量就是通过min(他左边板子的高度最大值,右边板子的高度最大值)算出来的。

这也就是前缀和以及后缀和,把每个位置的前缀和 和 后缀和算出来,然后取最小值就得到了当前位置的水桶容量。 然后用水桶的容量 - 当前位置的高度height[i] 就能算出当前位置的储水量。

class Solution:
    def trap(self, height: List[int]) -> int:
        n = len(height)
        pre_max = [0] * n
        pre_max[0] = height[0]
        ans = 0
        for i in range(1, n):
            pre_max[i] = max(pre_max[i-1], height[i])
        suf_max = [0] * n 
        suf_max[-1] = height[-1]
        for i in range(n-2, -1, -1):
            suf_max[i] = max(suf_max[i+1], height[i])
        for pre, suf, h in zip(pre_max, suf_max, height):
            ans += min(pre, suf) - h
        return ans 

法2:双指针法

初始化 前缀和后缀,因为前缀和后缀有一个 特点 那就是他的值是不会变小的,也就是说

当 pre_max < suf_max 的时候, 左指针指向的水桶的容量就已经固定了,因为取得是两者的较小值。 这个时候 ans += pre_max - height[left]   left = left + 1

当 suf_max < pre_max 的时候,右指针指向的水桶的容量就已经固定了,因为取得是两者的较小值。 这个时候 ans += suf_max - height[right]   right = right - 1

循环条件 left < right,这个大家可以画图思考一下,当left 和 right 相等的时候,两个指针都指向了最高的水桶,两者相等肯定是无法接水的,故循环结束。

class Solution:
    def trap(self, height: List[int]) -> int:
        left, right = 0, len(height) - 1
        ans = 0
        pre_max, suf_max = 0, 0
        while left < right:
            pre_max = max(pre_max, height[left])
            suf_max = max(suf_max, height[right])
            if pre_max > suf_max:
                ans += suf_max - height[right]
                right -= 1
            else:
                ans += pre_max - height[left]
                left += 1
        return ans  


总结

这节是对相向双指针的进一步应用

  • 14
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
相对路径和绝对路径是用来描述文件或资源在文件系统中位置的两种不同方式。 相对路径是相对于当前文件所处的目录而言的路径。它是以当前文件所在目录为参考基础,建立起的目录路径。因此,当保存于不同目录的文件引用同一个资源时,所使用的路径将不相同,因此称之为相对路径。\[1\] 绝对路径是从文件系统的根目录开始描述文件或资源的路径。它提供了完整的路径信息,不受当前文件所在目录的影响。无论文件在哪个目录中,绝对路径都能准确地指向该文件或资源。\[2\] 相对路径和绝对路径在使用上有一些区别。相对路径在引用资源时,可以使用相对于当前文件所在目录的路径,可以简化路径的书写。而绝对路径需要提供完整的路径信息,相对较长。\[2\] 相对路径的优点是当网页位置改变时,引用的资源路径仍然能够正确指向。而绝对路径的优点是即使网页被复制或链接到其他位置,引用的资源路径仍然能够正确指向。\[3\] 绝对路径的缺点是当网站的域名或目录结构发生变化时,需要手动修改所有引用资源的路径。而相对路径的缺点是当引用资源的文件和当前文件不在同一目录下时,需要使用特定的相对路径来引用资源。\[3\] 综上所述,相对路径和绝对路径是描述文件或资源位置的两种不同方式,它们在使用上有一些区别和优缺点。具体使用哪种路径取决于实际情况和需求。 #### 引用[.reference_title] - *1* [相对路径和绝对路径的区别](https://blog.csdn.net/Sweet__dream/article/details/81180045)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [相对路径./与../区别](https://blog.csdn.net/weixin_38633659/article/details/124373640)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值