cropper or striver

cropper or striver

在摆烂与奋进中反复横跳

📗盛最多水的容器 算法刷题打卡 第二天

难度:Medium#

题目:#

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

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

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

说明:你不能倾斜容器。

解析#

一眼 “秒” 了?#

粗看这道题,这不是很简单吗。用两个循环,循环计算水量并比较最大水量不就行了。甚至不需要记录在哪个时刻水最大。“秒” 了

    public int maxArea(int[] height) {
        //遍历
        int max = height.length;
        int maxarea = 0;
        for (int n = 0; n < max; n++) {
            for (int m = n; m < max; m++) {
                int temp = (m - n) * Math.min(height[n],height[m]);
                maxarea = Math.max(maxarea,temp);
            }
        }
        return maxarea;

    }

结果

好家伙,这么搞。数据太多了,两个循环导致处理超时了。

重新出发#

问题是两个循环嵌套导致的,所以目标就是减少循环,做到一次循环甚至更少。
看了提示需要用两个指针。从左右端点作为出发点。如果能做到一次只移动一个方向上的指针,那个就可以做到只循环一次。水量由水池的底(就是两个指针的距离)和高(两个指针所对应的高的最小值)的乘积决定。水池的底,在向中移动过程中只会不断变小。而高是两个指针对应高的最小值,如果说移动高的指针因为取的是最小值所以水池的高没有变化。水量甚至还会变小。移动水池低的边才有可以增加水量。
于是乎,就决定方式为循环一次,每次移动小的边,比较每次的水量和记录的最大水量,找出真正的最大水量。

    public int maxArea(int[] height) {
        //双指针
        int max = height.length;
        int i = 0;
        int j = max - 1;
        int maxarea = 0;
        for (int n = 0; n < max; n++) {
            maxarea = Math.max(maxarea, (j-i)*Math.min(height[i],height[j]));
            if (height[i] < height[j]) {
                i++;
            } else {
                j--;
            }
        }
        return maxarea;
    }

结果成了

image

继续优化#

我发现,在左右指针向中间移动的过程中。如果移动后的指针高度比移动前更低,那是不是就不用判断水池 “水量”,因为肯定变少了,直接继续移动。于是我用了两个标识来记录,提高代码的执行速度。
于是嘎嘎干

    public int maxArea(int[] height) {
        //双指针优化
        int max = height.length;
        int i = 0;
        int j = max - 1;
        int maxarea = 0;
        //两边的标识
        int maxHeightI = height[i];
        int maxHeightJ = height[j];
        //记录上次是左边指针(0)移动还是右边指针(1)移动
        int flag = 0;
        for (int n = 0; n < max; n++) {
            if (flag == 0) {
                if (height[i] < maxHeightI) {
                    i++;
                    continue;
                }else {
                    maxHeightI = height[i];
                }
            }
            if (flag == 1) {
                if (height[j] < maxHeightJ) {
                    j--;
                    continue;
                }else {
                    maxHeightJ = height[j];
                }
            }
            maxarea = Math.max(maxarea, (j-i)*Math.min(height[i],height[j]));
            if (height[i] < height[j]) {
                i++;
                flag = 0;
            } else {
                j--;
                flag = 1;
            }
        }
        return maxarea;

    }

结果果真有效
image

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。