LeetCode 11 容器最多能装多少水:掌握双指针技巧,解锁算法之美
2023-09-23 10:49:14
LeetCode 11 容器最多能装多少水 (标签: 数组 难度: 困难)
题目概述
给定一个由非负整数组成的数组 height ,其中每个数字 height[i] 表示坐标中的一个点 (i, height[i])。假设在坐标系中画出 n 条垂直线,垂直线 i 的两个端点分别为 (i, height[i]) 和 (i, 0) 。请找出这些垂直线之间的最大容器,即能够装最多水的容器。
例如,给定数组 height = [1, 8, 6, 2, 5, 4, 8, 3, 7] ,则可以形成如图所示的容器。
|
|
|
__ | __
/ \ | / \
/ \ | / \
/ \|/ \
| | |
|________|________|
0 1 2 3 4 5 6 7 8
在这个示例中,最大的容器位于序号为 1 和 8 的垂直线之间,其容量为 49。
解题思路
这道题目乍看起来似乎有些复杂,但如果我们仔细分析,就会发现其中隐藏着一些有趣的规律。首先,我们可以观察到,如果要使容器的容量最大,那么它的两条边必须尽可能地长,并且它们之间的距离也必须尽可能地大。其次,容器的容量只与两条边的长度和它们之间的距离有关,与两条边的具体位置无关。
基于这些观察,我们可以得出这样一个结论:如果我们能够找到两条边,使得它们的长度之积和它们之间的距离之积都最大,那么我们就找到了容量最大的容器。
为了找到这两条边,我们可以使用双指针技巧。我们将两个指针分别指向数组的开头和结尾,然后同时向中间移动。在移动的过程中,我们将不断比较两条边的长度之积和它们之间的距离之积,并将最大值记录下来。
如果我们遇到一条边比另一条边短,那么我们就移动较短的那条边,因为这样可以增加两条边的长度之积。如果我们遇到一条边比另一条边长,那么我们就移动较长的那条边,因为这样可以增加两条边的距离之积。
我们一直移动指针,直到它们相遇为止。此时,我们找到的两条边就是容量最大的容器的两条边。
代码实现
def maxArea(height):
"""
计算容器最多能装多少水。
参数:
height: 一个由非负整数组成的数组,表示每个点的坐标。
返回:
容器最多能装的水的容量。
"""
# 初始化两个指针
left = 0
right = len(height) - 1
# 初始化最大容量
max_area = 0
# 当两个指针没有相遇时,继续循环
while left < right:
# 计算当前容器的容量
area = min(height[left], height[right]) * (right - left)
# 更新最大容量
max_area = max(max_area, area)
# 移动较短的那条边
if height[left] < height[right]:
left += 1
else:
right -= 1
# 返回最大容量
return max_area
# 测试代码
height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
result = maxArea(height)
print("容器最多能装", result, "单位水。")
算法分析
- 时间复杂度:O(n),其中 n 是数组 height 的长度。这是因为双指针技巧只需要遍历数组一次。
- 空间复杂度:O(1),因为我们只需要几个变量来存储指针的位置和最大容量。
总结
LeetCode 11 容器最多能装多少水是一个经典的算法问题,它考察了算法设计和数据结构方面的知识。通过对这道题目的深入理解,我们不仅掌握了双指针技巧,还解锁了算法之美。在日后的编程实践中,这些知识和技巧都将对我们大有裨益。