leetcode11-盛最多水的容器

163 阅读2分钟

题目

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

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

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

说明:你不能倾斜容器。

示例 1:

输入: [1,8,6,2,5,4,8,3,7]

输出: 49

解释: 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

来源:力扣(LeetCode)

链接:leetcode.cn/problems/co…

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码

public class Leetcode11 {
    // 暴力
    @Deprecated
    public int maxArea0(int[] height) {
        int max = 0;
        for (int i = 0; i < height.length - 1; i++) {
            for (int j = i + 1; j < height.length; j++) {
                max = Math.max(max, (j - i) * Math.min(height[i], height[j]));
            }
        }
        return max;
    }

    // 双指针
    public int maxArea(int[] height) {
        int max = 0;
        int left = 0;
        int right = height.length - 1;
        while (right > left) {
            max = Math.max(max, (right - left) * Math.min(height[right], height[left]));
            if (height[right] > height[left]) {
                left++;
            } else {
                right--;
            }
        }
        return max;
    }
}

解释

法一:暴力遍历, 两个for循环去做;比较所有场景,记录下最大的那个。方法很简单清晰,但是复杂度过高,case无法全部过。仔细分析下这种方法,其实做了许多无用功,比如我们每次移动的都是右边的指针,当有一种情况,height[i]<height[j],这种时候无论怎么移动j,面积都不会变大了,因为此时的面积受限于值比较小的那个,即height[i]。所以其实用两层for循环的话,也可以加个判断,当height[i]<height[j]时,就直接跳到i+1的循环,不用移动j了

法二:双指针, 基于上面分析的,可以去掉一部分无用功;但是其实可以做的更彻底,去两个指针,left和right;从一开始就比较两端的大小,哪个小哪个就往中间移动,直到两者重合,期间记录下的最大的值就是我们需要的。

总结

这是非常重要、典型的双指针题目;第一次做确实无法想到这种方法,其实理解双指针就是一个分析去除无用功的逻辑。多做题总结即可