力扣-hot100(盛最多水的容器-双指针)

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。
  • n == height.length

  • 2 <= n <= 105

  • 0 <= height[i] <= 104

思路

容器的长是由两直线(宽)的距离决定的,容器的高是两直线中最短的那根确定的。所以我只需要两两遍历每条边,求一个max不就行了吗。

很明显 n = 10^5, n^2的操作是会超时的

代码如下

class Solution {
    public int maxArea(int[] height) {
        // 容器的长是由两直线的距离决定的,容器的高是两直线中最短的那根
        int n = height.length;
        int maxValue = 0;
        // 左边长
        for(int left = 0; left < n; left ++){
            // 右边长
            for(int right = left; right < n; right ++){
                int h = Math.min(height[left], height[right]);
                int c = right - left;
                maxValue = Math.max(maxValue, h * c);
            }
        }
        return maxValue;
    }
}

改进

实事上并不是每条边(高)都是有价值的,宽的价值是很好确定的,最两侧的边,为宽的最大权重。

思路:抓一头,先让宽的价值最大化,此时的边是最两侧的,为了不漏掉中间有很高的,肯定要从两侧往中间移动,移动哪条? 那肯定是移动更矮的那根, 高的那根更能创造价值

补充: 这样做会不会漏掉,这里漏掉的情况只可能有一种,就是当两个高相等时,移动了随机一根,但是要明确的是高的长度是由最短的那根确定下来的,即便你后面有很长的,也会被这两根相同的限制,所以不论移动哪根都是一样的。如果你后面有很短的那更不可能了,后面的宽和高都小的话,面积只会比当前的更小,我们求的是最大面积。

代码如下:

class Solution {
    public int maxArea(int[] height) {
        // 让宽处于最大,即最两侧
        int left = 0, right = height.length - 1;
        // 定义最大面积
        int maxValue = 0;
        // 宽、高
        int w, h;
        while(left < right){
            // 宽为两者之间的距离
            w = right - left;
            // 高取最小的那根
            h = Math.min(height[left], height[right]);
            // 面积
            maxValue = Math.max(maxValue, w * h);
            // 让更矮的那端向中间移动
            if(height[left] < height[right]) left ++;
            else right --;
        }
        return maxValue;
    }
}

你可能感兴趣的:(LeetCode,-,Hot100,leetcode,算法,java)