双指针法解盛最多水容器问题:为何无需遍历所有元素对?
容器盛水问题双指针解法的核心逻辑解释
首先明确容器储水量的计算规则:储水量 = 两条线中较矮的高度 × 两条线之间的水平距离。
双指针解法从数组两端出发(左指针在起点,右指针在终点),每次移动高度较小的那个指针,这种方式能跳过大量配对却不会错过最优解,核心逻辑如下:
假设当前左指针位置为L,右指针为R,对应的高度是h[L]和h[R],且h[L] < h[R]。
此时,以L为左边界的所有可能容器(即L分别和L+1、L+2、...、R配对)中,最大的储水量就是当前的h[L]*(R-L)。
因为任何和L配对的右边界如果在R左侧,水平距离会更小,而储水量的高度最多只能是h[L](毕竟h[L]是两条线中更矮的那个),所以这些配对的储水量必然比当前的小,完全没有必要再检查。因此可以直接把左指针右移,排除所有以L为左边界的配对。反之,如果h[R] <= h[L],同理,以R为右边界的所有配对(即L、L+1、...、R-1分别和R配对)中,当前的储水量已经是最大的。因为水平距离缩小后,高度最多是h[R],储水量只会更小,所以直接把右指针左移即可。
每一步操作都能排除一整组不可能成为最优解的配对,因此整个过程只需要遍历数组一次,时间复杂度降到O(n)。
附上官方双指针解法代码:
var maxArea = function (height) { let biggestArea = Number.MIN_VALUE; let leftPointer = 0; let rightPointer = height.length - 1; while (leftPointer < rightPointer) { let leftHeight = height[leftPointer]; let rightHeight = height[rightPointer]; let heightToUse = leftHeight < rightHeight ? leftHeight : rightHeight; let area = heightToUse * (rightPointer - leftPointer); biggestArea = Math.max(biggestArea, area); if (leftHeight < rightHeight) { leftPointer++; } else { rightPointer--; } } return biggestArea; };
内容的提问来源于stack exchange,提问作者leon100
相关产品推荐
相关产品推荐

