图解LeetCode 热题中的双指针问题——以“盛最多水的容器” 为例,不能更细致了,包教包会!

分类->leetcode->中等题

题目 LeetCode 热题100-> ​ 11. 盛最多水的容器 ​

https://leetcode.cn/problems/container-with-most-water/description/?envType=study-plan-v2&envId=top-100-liked

这是双指针算法中的典型例题,也是面试中经常出现的题,下面我将以LeetCode 热题100中的 11. 盛最多水的容器为例,通过图解详细步骤的方式讲解这类问题应该怎么做。


题目介绍

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

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

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

输入:[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

提示:

  • n == height.length
  • 2 <= n <= 105
  • 0 <= height[i] <= 104

解题思路

题目有几个关键字“数组”、“找出其中的两条线”、“最多”,将选择限定在了数组,并且要选两个数组内元素,还要求最大值,那么我们应该想到使用双指针解题。

既然已经决定使用双指针了,那需要解决的问题就变成了四个:

  1. 两个指针的起始位置?
  2. 遍历结束的条件?
  3. 每次移动后得到的值是什么?
  4. 指针移动的条件是什么?

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

容纳的水量即两条线与x轴围成的“矩形”面积,这里需要提到一点,那就是矩形的高由两条线中短的那一条决定,这个很像以前经常听到的“短板效应”。

设两个指针分别为 i 和 j,表示选出的两条线的序号,该序号对应的数组内的值表示线条的长度,这决定了矩形的高,矩形的长为两条线的序号之差,将面积设为S,即每次指针移动后得到的值。
 S = | j - i | * min ( height[i] , height[j])

那么指针的起始位置是什么呢?既然我们要求最大值,理想状态的最大值就是长和高都最大,这样的面积就最大。那就以长最大的时刻为起始位置,即 i 在头,j 在尾

初始位置时矩形的长达到最大值,指针再怎么移动,长度只会减小,那为了获得比此时还要大的矩形面积,只能考虑增加矩形的高。
如何增加矩形的高?应该挑选两个线条中更短的那一条向内移动
如果 i 短,i 右移;如果 j 短,j左移。

每次指针移动后,根据S的值更新max,直至两个指针相遇(即矩形长为0)

为了更好地演示具体的步骤,我根据题目中的示例 [1,8,6,2,5,4,8,3,7]绘制了步骤图解,如下所示:


参考代码

class Solution {
    public int maxArea(int[] height) {
        int i = 0, j = height.length - 1;
        int max = Integer.MIN_VALUE;
        while (i != j) {
            max = max > (j - i) * Math.min(height[i], height[j]) ? max : (j - i) * Math.min(height[i], height[j]);
            if (height[i] < height[j]) {
                i++;
            } else {
                j--;
            }
        }
        return max;

    }
}

最近正在学习算法和刷 leetcode,发现图解的方式更能加深印象,就记录了下来。
不过一个人学感觉没有什么动力,有些题也想不太明白,创建了一个算法交流群,如果有同在刷题的小伙伴,欢迎加入~

qq群号:643418253

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值