leetCode-11: 盛最多水的容器

题目描述

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。

示例

示例 1:
Alt输入:[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

解题过程

思路及步骤
此题即为在数组中找出两个元素,使之围成的矩形区域面积最大,求这个最大的区域面积。
(1)矩形的面积 S = 长 * 宽,依题意而言,长 = 两个元素下标的差值,即 j - i;宽 = 两个元素中较小的一个的取值,即 Math.min(height[i], height[j]);
(2)由此可知,S = Math.min(height[i], height[j]) * (j - i);
(3)使用 while 循环加双指针的方法遍历数组元素,i 从第 0 号元素开始,j 从第 height.length - 1 好元素开始,循环满足的条件为:i < j;
(4)每次循环都去计算一下当前两个指针围成的矩形区域的面积,并且与上一次两个指针围成的区域面积进行比较,取较大者作为新的 S;
(5)得到新的 S 之后需要考虑指针的移动,到底是左指针 i 向右移动,还是右指针 j 向左移动,取决于当前 i 和 j 对应的元素大小,若 height[i] < height[j],说明左指针的值小,要做的就是改变这个最小值,所以 i++(也可以使用“短板效应”来理解,既然 height[i] < height[j],说明左指针为短板,需要改变,所以直接 i++);
(6)若 height[i] > height[j],说明右指针的值小,要做的就是改变这个最小值,所以 j--;
(7)若 height[i] == height[j],此时左右指针的值大小一样,可任意移动,i++ 或 j-- 均可
注意:移动短板时只需要考虑当前两个指针哪个为短板即可,哪个短就改变哪个,并不需要去考虑改变之后的短板(即,若 height[i] < height[j],则 i++,而不需要去考虑 height[i + 1] 和 height[j - 1] 的值),因为始终需要进行新的 S 与旧的 S 的比较。
代码展示
public class maxArea {

    public static int maxArea(int[] height) {
        int maxArea = 0;
        int i = 0;
        int j = height.length - 1;
        while (i < j) {
            // 左指针的值
            int iValue = height[i];
            // 右指针的值
            int jValue = height[j];
            // 当前左右指针围成的区域的面积
            int currentArea = Math.min(iValue, jValue) * (j - i);
            maxArea = Math.max(maxArea, currentArea);
            // 改变短板, 左边短就向右移, 右边短就向左移, 左右一样则左右随机移动
            if (iValue <= jValue) {
                i++;
            }
            if (iValue > jValue) {
                j--;
            }
        }
        return maxArea;
    }

    public static void main(String[] args) {
        int[] height = {1,8,6,2,5,4,8,3,7};
        int result = maxArea(height);
        System.out.println(result);
    }
}
图解示例

{1,8,6,2,5,4,8,3,7} 为例:
(1)初始化:左指针 i = 0,从前往后遍历,右指针 j = 数组长度 - 1,从后往前遍历,maxArea = 0,作为最终要返回的最大的面积;
(2)开始循环,当 i = 0,j = 8 时,当前两个指针围成的矩形区域面积 currentArea = Math.min(height[i], height[j]) * (j - i) = 1 * 8 = 8,因 currentArea > maxArea,所以更新 maxArea = currentArea = 8,然后移动短板,因为 height[i] < height[j],所以将左指针 i 自增 1;
在这里插入图片描述(3)当 i = 1,j = 8 时,当前两个指针围成的矩形区域面积 currentArea = Math.min(height[i], height[j]) * (j - i) = 7 * 7 = 49,因 currentArea > maxArea,所以更新 maxArea = currentArea = 49,然后移动短板,因为 height[i] > height[j],所以将右指针 j 自减 1;
Alt(4)当 i = 1,j = 7 时,当前两个指针围成的矩形区域面积 currentArea = Math.min(height[i], height[j]) * (j - i) = 3 * 6 = 18,因 currentArea < maxArea,所以无需更新 maxArea,然后移动短板,因为 height[i] > height[j],所以将右指针 j 自减 1;
在这里插入图片描述(5)当 i = 1,j = 6 时,当前两个指针围成的矩形区域面积 currentArea = Math.min(height[i], height[j]) * (j - i) = 8 * 5 = 40,因 currentArea < maxArea,所以无需更新 maxArea,然后移动短板,因为 height[i] == height[j],左右指针皆可移动,我们选择将左指针 i 自增 1;
在这里插入图片描述(6)当 i = 2,j = 6 时,当前两个指针围成的矩形区域面积 currentArea = Math.min(height[i], height[j]) * (j - i) = 6 * 4 = 24,因 currentArea < maxArea,所以无需更新 maxArea,然后移动短板,因为 height[i] < height[j],所以将左指针 i 自增 1;

在这里插入图片描述(7)当 i = 3,j = 6 时,当前两个指针围成的矩形区域面积 currentArea = Math.min(height[i], height[j]) * (j - i) = 2 * 3 = 6,因 currentArea < maxArea,所以无需更新 maxArea,然后移动短板,因为 height[i] < height[j],所以将左指针 i 自增 1;
在这里插入图片描述(8)当 i = 4,j = 6 时,当前两个指针围成的矩形区域面积 curretreXKwva = Math.min(height[i(, height[j])https:/(4)当 i = 4,j = 6 时,当前两个指针围成的矩形区域面积 currentArea = Math.min(height[i], height[j])] * (j - i) = 5 * 2 = 10,因 currentArea < maxArea,所以无需更新 maxArea,然后移动短板,因为 height[i] < height[j],所以将左指针 i 自增 1;
在这里插入图片描述(9)当 i = 5,j = 6 时,当前两个指针围成的矩形区域面积 currentArea = Math.min(height[i], height[j]) * (j - i) = 4 * 1 = 4,因 currentArea < maxArea,所以无需更新 maxArea,然后移动短板,因为 height[i] < height[j],所以将左指针 i 自增 1;
在这里插入图片描述(10)当 i = 6,j = 6 时,不满足 while 循环的条件,得到最终的 maxArea = 49。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值