Go-Leecode-盛最多水的容器(刷题记录)

161 篇文章 12 订阅
本文介绍了如何解决计算机科学中的一个经典问题——盛最多水的容器。通过分析给定的非负整数数组,找到能容纳最大水量的两条线段。文章详细解释了暴力遍历和双指针法两种解决方案,并提供了代码实现,强调双指针法的效率。内容适合对算法和数据结构感兴趣的读者。
摘要由CSDN通过智能技术生成

原文地址:Go-Leecode-盛最多水的容器(刷题记录)

给定n个非负整数a1、a2、a3...an,没个数代表坐标中的一个点(i,ai),在坐标轴x上作n条垂线,垂直线i的两个端点分别为(i,ai)和(i,0),找出其中的两条线,使得其与x轴共同构成的容器在不倾斜的情况下可以容纳最多的水。

示例一:

输入:[1,8,6,2,5,4,8,3,7]输出:49

示例二:

输入:height = [1,1]输出:1

示例三:

输入:height = [4,3,2,1,4]输出:16

示例四:

输入:height = [1,2,1]输出:2

需说明的内容如下:

  1. n = height.length。

  2. 2 <= n <= 3 * 104。

  3. 0 <= height[i] <= 3 * 104。

针对示例一的输入和输出做一个说明,如图:


上图中垂直线代表输入数组[1,8,6,2,5,4,8,3,7],此时容器能够容纳水(表示为蓝色部分)的最大值为49。

如果这么表达比较不清晰的话,我们可以换个角度来理解,还是上图中的内容,我们既然要求是容水量最大,那肯定是需要计算这个容器的容积,但是按题目中的要求来看,明显只有高和长或是高和宽,相当于一个容器的切面,在这种情况下,如果想拿到最大的容水量,那就不能只考虑这个容器的高度,还得考虑这个容器的长或宽,只有高和长或是高和宽相乘为最大值时,方可取出题目中所要求的数据。

既然目标已经明确了,我们现在要做的就是确认那个是高,那个是长或是宽,很明显,数组中的每个元素就相当于不同的高,那么长或是宽的奥秘就在于数组的元素的位置,比如第一次出现8和最后一次出现的7这两个元素,它们中间相差七个位置,而水容量在不倾斜容器的情况下取决于容器的最低端,所以我们就可以就得出来它的水容量为49。

解决上述问题我这边能想到的最简单的方式就是暴力遍历做对比,如下:

func maxArea(height []int) int {
    n := len(height)
    if n <= 1 {
        return 0
    }
    
    maxMulti := 0
    for i := 0; i < n-1; i++ {
        for j := i + 1; j < n; j++ {
            w := j - i                     // 宽
            h := min(height[i], height[j]) // 高
            maxMulti = max(maxMulti, w*h)  // 比较面积
        }
    }
    
    return maxMulti
}


网上找了一种优雅的方式-双指针法,它的原理就是两条线段之间的面积受限与最短的线段,线段间距越长,面积越大,使用 2 个指针指向首部和尾部,将短指针向长指针方向移动,看能不能找到更长的线,使面积更大,这种原理的依据是向长线方向每次移动1格,虽然宽度-1,但是(高度变高)*(宽度-1) >= 高度*宽度,实现如下:

func maxArea(height []int) int {
    maxMulti := 0
    left, right := 0, len(height)-1
    for left < right {
        w := right - left
        h := min(height[left], height[right])
        maxMulti = max(maxMulti, w*h)
        if height[left] <= height[right] {
            left++ // 往右边走找更长的线
        } else {
            right-- // 往左边走
        }
    }
    
    return maxMulti
}

又是一种较为高深的说法。。。

至此,本次分享就结束了,后期会慢慢补充。

以上仅为个人观点,不一定准确,能帮到各位那是最好的。

好啦,到这里本文就结束了,喜欢的话就来个三连击吧。

扫码关注公众号,获取更多优质内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值