盛最多水的容器

80 阅读1分钟

题目

双指针

public class Main {
    public static void main(String[] args) {

        Main main = new Main();
        int [] height = new int[] {1, 8, 6, 2, 5, 4, 8, 3, 7};
        main.maxArea(height);
    }

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

基本思路

  1. 暴力解法就是两个循环嵌套, 每次保留(j - i) * Math.min(height[j], height[i])的值, 这样会枚举出所有的可能.

  2. 为了能减少计算次数, 首先根据计算公式(j - i) * Math.min(height[j], height[i]), 当我们控制(j - i)的变化的时候, 当Math.min(height[j], height[i])越大结果越大, 因此我们控制(j - i)从最大变化到最小, 得到每次Math.min(height[j], height[i])最大的情况, 这样大大减少了计算次数

  3. 以最大宽度(0, height.lenght - 1)变化到(1, height.length - 1)和(0, height.length - 2)为例.本身宽度减去1带来了两种可能到索引范围, 但是可以发现通过比较heghit[0]和height[height.lenght - 1]的值发现, 肯定是把值较小的那个值移动, 如果移动后变大, 正是我们期望的, 如果移动后变小, 对面积的影响也比移动大的那个小.

  4. 根据这种思路, 我们发现虽然还有冗余的结果, 还是计算数量大大下降, 同时我们也发现似乎思路也就是dp[j - i], 也具有了转台转移方程 即dp[j - i - 1] = dp[j - i] + xxx得到, 但是与自底向上不同, 要自顶向下, 因为顶部向下的过程中, 可能解是越来越多的