给定一个长度为 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
步骤 1:问题性质分析
这个问题属于双指针算法的经典应用场景,通常用来寻找数组中符合条件的最大值。在此问题中,我们需要找到一对垂线使得它们与 x
轴构成的容器可以容纳最多的水量。
-
输入条件:
- 整数数组
height
,长度为n
,表示n
条垂直线的高度。 - 每一条垂线的坐标为
(i, 0)
和(i, height[i])
,i
是该垂线的索引。
- 整数数组
-
输出条件:
- 返回两条垂线间的容器可以容纳的最大水量。
-
约束条件:
2 <= n <= 10^5
,保证数组至少有两条线。0 <= height[i] <= 10^4
,高度可以为0,表示没有高度的线。
-
问题的几何本质:
- 两条垂线的
x
坐标距离越大,容器的宽度越大。 - 两条垂线中较短的一条决定了容器的高度,容器的容量等于
min(height[left], height[right]) * (right - left)
,即两条线中较短的高度乘以它们的横向距离。
- 两条垂线的
步骤 2:算法设计思路
我们可以使用双指针法来解决这个问题。双指针法能够在O(n) 时间复杂度内找到结果,符合题目对大规模数据的要求。
1. 初始化双指针
将两个指针分别放在数组的两端,一个指向最左边的线,另一个指向最右边的线。这样可以从最大可能的宽度开始计算。
2. 计算当前容器的容量
每次根据当前两条线的高度和它们的距离计算当前容器的容量。容量公式为:
3. 移动指针
为了尽可能找到更大的容器,我们要移动指针。移动规则是:
- 总是移动高度较小的那条线的指针。这是因为容器的高度是由较短的那条线决定的,移动较小的高度有机会遇到更高的线从而增加容量。
4. 终止条件
当左指针与右指针相遇时,循环终止。此时我们已经检查过了所有可能的容器,最大值也已找到。
5. 时间复杂度
双指针从两端逐步向中间移动,整个过程最多遍历数组一次,因此时间复杂度为 O(n)。
6. 空间复杂度
由于使用了常数空间的双指针,空间复杂度为 O(1)。
步骤 4:算法的启发
-
双指针法的应用:通过左右夹逼的方式,我们有效减少了计算的复杂度,这是双指针法处理连续子序列问题的一个典型应用。
-
效率的提升:相比暴力解法(遍历所有的可能组合,时间复杂度为 O(n²)),双指针法的时间复杂度为 O(n),这是一个显著的优化。在处理大规模数据时,这种优化尤为重要。
-
数据规模处理能力:通过这一问题的解决,我们能看出,在大规模数据集上,优化算法的时间复杂度至关重要。很多问题可以通过空间换时间或者特定的策略,如双指针法,达到更高的效率。
步骤 5:实际应用场景
双指针法的思想可以广泛应用于需要在一个连续空间中寻找最优解的场景。一个实际应用的例子是物流仓储的优化:
- 物流场景示例:假设在一个仓库中,有一系列货架,每个货架的宽度固定,但高度不同。要在两个货架之间摆放最多的货物,要求货物的高度不能超过较矮的货架高度,且摆放的区域宽度是两个货架之间的距离。在这种情况下,我们可以用双指针法来找到能摆放最多货物的两组货架。
实现方法:
- 使用货架的编号作为数组的索引,货架的高度作为数组的元素。通过双指针法找到能够容纳最多货物的两组货架,帮助优化仓库的布局,提高货物摆放效率。通过这种方式,仓库管理系统可以自动推荐货物的最佳存放位置,提高物流的吞吐量。