11. 盛最多水的容器

128 阅读3分钟

题目

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明: 你不能倾斜容器。

示例 1:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49 
解释: 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49

示例 2:

输入: height = [1,1]
输出: 1

提示:

  • n == height.length
  • 2 <= n <= 105
  • 0 <= height[i] <= 104

解题思路

最初的方法 是采用了双指针策略,即设置两个指针分别指向数组的首尾,然后向中间移动,每次移动较短的线段指针,并更新最大面积。

最初的代码

class Solution:
    def maxArea(self, height: List[int]) -> int:
        left, right = 0, len(height) - 1
        max_water = 0
        while left < right:
            # 计算当前容器的水量
            water = (right - left) * min(height[left], height[right])
            max_water = max(max_water, water)
            
            # 移动较短的线段
            if height[left] < height[right]:
                left += 1
            else:
                right -= 1
        return max_water

优化方法

尽管双指针法已经很有效,但我们可以通过减少某些操作来优化这个解法。例如,减少对 min 函数的调用,并直接在比较时计算面积,这样可以减少每次迭代的计算量。

运行优化后的代码

class Solution:
    def maxArea(self, height: List[int]) -> int:
        left, right = 0, len(height) - 1
        max_area = 0
        while left < right:
            # 减少函数调用,直接在这里比较
            if height[left] < height[right]:
                area = height[left] * (right - left)
                left += 1
            else:
                area = height[right] * (right - left)
                right -= 1
            if area > max_area:  # 减少不必要的赋值操作
                max_area = area
        return max_area

运行

print(maxArea([1,8,6,2,5,4,8,3,7]))  # 应输出 49

总结

在解决 "盛最多水的容器" 问题时,我们从一个基于双指针的基础实现出发,进行了优化以提高代码执行效率。

优化前的实现: 初始解法利用了双指针法,指针分别从数组的两端向中间移动,每次迭代都计算由两个指针形成的容器的容量,并更新最大值。关键代码如下:

area = min(height[left], height[right]) * (right - left)

这个实现简洁明了,但每次迭代都要调用 min 函数来计算两个指针所指高度的最小值,这会导致不必要的重复计算。

优化后的实现: 在优化版本中,我们避免了调用 min 函数,而是通过比较指针所指的两个高度,直接进行计算:

if height[left] < height[right]:
    area = height[left] * (right - left)
    left += 1
else:
    area = height[right] * (right - left)
    right -= 1

这种方法减少了函数调用,直接在条件判断中计算宽度和高度。

优化前后的对比: 优化后的实现在执行时间上更为高效,尤其是在涉及大数据量的情况下,每次迭代避免了额外的函数调用,减少了执行时间的常数因子。虽然时间复杂度在理论上保持不变,仍为 O(n),但在实际运行中,优化后的代码更快,因为它执行更少的操作并拥有更高的操作效率。在极端情况下,这种细微的优化可能会带来显著的性能提升。

题目链接

盛最多水的容器