原题:给定一个长度为 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。

思路

看到示例第一时间想到用双指针解决,关键在于何时移动左指针或右指针,并更新结果的最大值

记左指针为lp,右指针rp,记[lp, rp]区间能盛水的值为 y,由短板效应易知 *y = min(height[lp], height[rp]) (rp – lp)**

初始时令lp = 0,rp = n – 1,假设某状态下height[lp] < height[rp],考虑此时如何移动指针

  • 若将lp右移,则当 height[lp + 1] > height[lp] 时,y可能增大
  • 若将rp左移,则无论 height[rp – 1] 大小,y一定减小

我们期望得到更大的值,故此时应将lp右移,反之如果height[lp] > height[rp],则应将rp左移,然后计算新位置 y’的值与原来比较并更新最大值

代码(js):

var maxArea = function(height) {
    let res = 0
    let lp = 0, rp = height.length - 1
    while (lp < rp) {
        if (height[lp] > height[rp]) {
            // 更新结果最大值,左移rp
            res = Math.max(res, height[rp] * (rp - lp))
            --rp
        } else {
            // 更新结果最大值,右移lp
            res = Math.max(res, height[lp] * (rp - lp))
            ++lp
        }
    }
    return res
};

再简化亿下代码:

var maxArea = function(height) {
    let res = 0
    let lp = 0, rp = height.length - 1
    while (lp < rp) {
        res = Math.max(res, height[lp] > height[rp] ? height[rp] * (rp-- - lp) : height[lp] * (rp - lp++))
    }
    return res
};

复杂度:需要遍历一遍数组,且储存双指针变量,故 时间复杂度O(n),空间复杂度O(1)

Leave a Reply

Your email address will not be published. Required fields are marked *