[LeetCode 11. 盛最多水的容器] | 刷题打卡

127 阅读2分钟
  • 掘金团队号上线,助你 Offer 临门! 点击 查看活动详情

本题核心

不管思考过程多长,解出来以后,发现殊途同归。

题目描述

给你n个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画n条垂直线,垂直线 的两个端点分别为 (i, ai)(i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器。

解题思路

https

示例 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
示例 3:

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

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

提示:
n = height.length
2 <= n <= 3 * 104
0 <= height[i] <= 3 * 104

解题代码

两天的解法演变过程,从二分->双循环->双指针

一开始想到的是用单循环找出整个数组最大值,然后在通过最大值将数组分为2个数组,
分别进行检索,找出面积最大的步长。然后代码执行错误。
 public int maxArea(int[] height) {
        int maxTag = 0;
        int maxValue = 0;
        for (int i = 0; i < height.length; i++) {
            if (maxValue < height[i]) {
                maxValue = height[i];
                maxTag = i;
            }
        }
        int maxSize = 0;
        int maxStep = 0;
        int minValue = 0;
        if (height.length - maxTag > maxTag) {//还能向右
            for (int i = maxTag + 1; i < height.length; i++) {
                int step = i - maxTag;//跨度
                if (Math.min(maxValue, height[i]) * step > maxSize) {
                    maxSize = Math.min(maxValue, height[i]) * step;
                    minValue = height[i];
                    maxStep = step;
                }
            }
        } else {
            for (int i = 0; i < maxTag; i++) {
                if (Math.min(maxValue, height[i]) * i > maxSize) {
                    maxSize = Math.min(maxValue, height[i]) * i;
                    minValue = height[i];
                    maxStep = i;
                }
            }
        }
        return Math.min(maxValue, minValue) * maxStep;
    }

接着想着暴力解,双循环

     public int maxArea(int[] height) {
        int w = 0;//
        int h = 0;//
        int maxSize = 0;//找出最大面积的 宽和高
        for (int i = 0; i < height.length; i++) {
            for (int j = 0; j < height.length; j++) {
                int diffH = Math.min(height[i], height[j]);
                int diffW = (j - i);
                if (i < j && diffH * diffW > maxSize) {
                    w = diffW;
                    h = diffH;
                  maxSize = diffH * diffW;
                }
            }
        }
        return w*h;
    }

但是双循环在遇到数组过大的时候会出现超时。

WX20210415-102957@2x.png

那么既要循环,又要找到2个左边界和右边界的话。那就只能用while循环了。

 public int maxArea(int[] height) {
        int maxSize = 0;//找出最大面积的 宽和高
        int i = 0;//左指针
        int j = height.length - 1;//右指针
        while (true) {
            if (i >= j) {//交叉
                break;
            }
            int leftValue = height[i];
            int rightValue = height[j];
            int value = Math.min(leftValue, rightValue);
            int size = value * (Math.abs(j - i));
            if (size > maxSize) {
                maxSize = size;
            }
            if (leftValue > rightValue) {//如果左边指针对应的value大于右边指针
                j--;//移动右边的指针
            } else {//移动左边的指针
                i++;
            }
        }
        return maxSize;
    }

最后优化下代码

  public int maxArea(int[] height) {
        int maxSize = 0;//找出最大面积的 宽和高
        int i = 0;
        int j = height.length - 1;
        while (i < j) {
            int value = Math.min(height[i], height[j]);
            maxSize = Math.max(value * (j - i), maxSize);
            if (height[i] > height[j]) {
                j--;
            } else {
                i++;
            }
        }
        return maxSize;
    }

WX20210415-103819@2x.png

看看题解了解下其他姐法

##总结

嘿嘿,作为经常做预防老年痴呆难度的醋君,今天挑战了下中级,也不过如此。哼(ˉ(∞)ˉ)唧

~骑士君,ヾ(◍°∇°◍)ノ゙加油啊