lc-盛水最多的容器

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

快速一栏:

  1. 暴力拆解
  2. 双指针

感觉自己进步很大,第一反应就是双指针,但是对双指针的移动条件不是很明确,所以先上一轮暴力解法,时间复杂度O(N2),空间复杂度O(N)。

整体思路是在以i开头的所有框中找到最大的存入max[i]中,依次递推,再在max[i]中找最大值,简单粗暴,实际上也AC了:

    public int maxArea(int[] height) {
        int len = height.length;
        int[] max = new int[len];
        for(int i = 0; i < len; i ++) {
            for(int j = i + 1; j < len; j ++) {
                if((j - i) * Math.min(height[i], height[j]) > max[i])
                    max[i] = (j - i) * Math.min(height[i], height[j]);
            }
        }
        int res = 0;
        for(int val : max) {
            if(res < val)
                res = val;
        }
        return res;
    }

当然,跑完的成绩并不优秀,再回到双指针的方法,双指针基本思想是:从两端开始,计算由left和right构成的矩形,之后将其中较矮的那边向对侧移动一格。原理是把不可能的选项排除掉。

假设我们把高的那个移动若干格,矮的不动,很容易理解得到的结果一定小于初始矩形的面积。所以虽然不知道高边不动的结果是是不是最优解,但矮边不动高边动的结果一定不是,所以可以排除。

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

你可能感兴趣的:(lc-盛水最多的容器)