建议参考下面视频
题目描述
给定一个数组height,长度为n,每个数代表坐标轴中的一个点的高度,height[i]是在第i点的高度。请问从中选2个高度与x轴组成的容器最多能容纳多少水。
约束条件
- 不能倾斜容器
- 当n小于2时,视为不能形成容器,返回0
- 容纳的水量不会超过整形范围(231-1)
数据范围
- 0 <= height.length <= 105
- 0 <= height[i] <= 104
解题思路
方法:双指针法
这道题可以使用双指针的方法来解决。基本思路是:
- 使用两个指针left和right,初始分别指向数组的左右两端
- 计算当前两个指针位置可以容纳的水量
- 移动较小高度的指针(因为移动较大的高度不可能得到更大的面积)
- 重复步骤2-3直到两个指针相遇
时间复杂度分析
- 时间复杂度:O(n) - 每个指针最多移动n次
- 空间复杂度:O(1) - 只使用常数额外空间
代码实现
int maxArea(int* height, int heightLen) {
// 初始化变量:
// max:用于存储最大面积
// left:左指针,初始指向数组的第一个元素
// right:右指针,初始指向数组的最后一个元素
int max = 0;
int left = 0;
int right = heightLen - 1;
// 当左指针小于右指针时,继续循环
while (left < right) {
// 计算当前左右指针之间的面积:
// 面积 = 宽度 × 较短的高度
// 宽度为左右指针的索引差 (right - left)
// 较短的高度为 height[left] 和 height[right] 中的较小值
int temp = (right - left) * (height[left] > height[right] ? height[right] : height[left]);
// 更新最大面积:
// 如果当前面积 temp 大于之前的最大面积 max,则更新 max
max = max > temp ? max : temp;
// 移动指针:
// 为了寻找更大的面积,需要移动较短高度的指针,因为移动较长高度的指针无法增加面积
if (height[left] > height[right]) {
// 如果左高度大于右高度,移动右指针:
// 记录当前右高度
int cur = height[right];
// 移动右指针,直到找到比当前右高度更高的柱子
while (left < right && height[right] <= cur)
right--;
} else {
// 如果右高度大于或等于左高度,移动左指针:
// 记录当前左高度
int cur = height[left];
// 移动左指针,直到找到比当前左高度更高的柱子
while (left < right && height[left] <= cur)
left++;
}
}
// 返回最终的最大面积
return max;
}
示例分析
示例1
输入:[1,7,3,2,4,5,8,2,7]
返回值:49
示例2
输入:[2,2]
返回值:2
示例3
输入:[5,4,3,2,1,5]
返回值:25
解题技巧
-
初始化指针:将左指针指向数组开头,右指针指向数组末尾。
-
计算面积:面积 = 两指针之间的距离 × 较小的高度。
-
指针移动策略:
- 始终移动较小高度的指针
- 如果高度相等,可以移动任意一个指针
- 移动时可以跳过不可能产生更大面积的位置
-
优化技巧:
- 使用while循环跳过相同高度的位置
- 及时更新最大面积
常见错误
- 忘记处理数组长度小于2的边界情况
- 面积计算公式错误
- 指针移动策略不当
- 没有正确处理相等高度的情况