分类->leetcode->中等题
题目 LeetCode 热题100-> 11. 盛最多水的容器
这是双指针算法中的典型例题,也是面试中经常出现的题,下面我将以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
解题思路
题目有几个关键字“数组”、“找出其中的两条线”、“最多”,将选择限定在了数组,并且要选两个数组内元素,还要求最大值,那么我们应该想到使用双指针解题。
既然已经决定使用双指针了,那需要解决的问题就变成了四个:
- 两个指针的起始位置?
- 遍历结束的条件?
- 每次移动后得到的值是什么?
- 指针移动的条件是什么?
题目要求的是“找出其中的两条线,使得它们与 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