面试经典算法题5 – 盛最多水的容器
LeetCode.11
公众号:阿Q技术站
问题描述
给定一个长度为 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
思路
这道题其实就跟求面积一样,根据高宽求最大面积。
- 初始化左指针
left
指向数组的开头,右指针right
指向数组的结尾,。 - 使用high取最小高度,wide记作右指针right - 左指针left。
- 计算当前容器的容量,并更新最大值。
- 如果
height[left] < height[right]
,说明左边的线段较短,我们希望找到更长的线段,因此移动左指针向右移动一位。 - 如果
height[left] >= height[right]
,说明右边的线段较短或者相等,我们希望找到更高的线段,因此移动右指针向左移动一位。 - 重复步骤 2-4,直到两个指针相遇。
演示过程
这里根据给的示例1给大家做个步骤演示。
- 初始化left = 0, right = height.size() - 1。
此时height[left] < height[right],area = height[left] * (right - left) = 1 * (8 - 0) = 8
- height[left] < height[right],将左指针右移。
此时height[right] < height[left],area = height[right] * (right - left) = 7 * (8 - 1) = 49
- height[left] > height[right] ,将右指针左移。
此时height[left] > height[right],area = height[right] * (right - left) = 3 * (7 - 1) = 18
- height[left] > height[right],将右指针左移。
此时height[left] = height[right],area = height[right] * (right - left) = 8 * (6 - 1) = 40
- 这个时候 height[right] = height[left],移动哪个都可以,这里继续将右指针左移吧。
此时height[left] > height[right],area = height[right] * (right - left) = 4 * (5 - 1) = 16
- height[left] > height[right],将右指针左移。
此时height[left] > height[right],area = height[right] * (right - left) = 5 * (4 - 1) = 15
- height[left] > height[right],将右指针左移。
此时height[left] > height[right],area = height[right] * (right - left) = 2 * (3 - 1) = 4
- height[left] > height[right],将右指针左移。
此时height[left] > height[right],area = height[right] * (right - left) = 6 * (2 - 1) = 6
- height[left] > height[right],将右指针左移。这时left就不小于right了,跳出循环。继而得出max_area = 49
参考代码
C++
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int maxArea(vector<int>& height) {
int area = 0;
int left = 0;
int right = height.size() - 1;
while (left < right) {
int high = min(height[left], height[right]); // 计算当前两条线段的最小高度
int wide = right - left; // 计算当前两条线段的宽度
area = max(area, high * wide); // 计算当前容器的容量并更新最大值
if (height[left] < height[right]) {
// 如果左边的线段较短,向右移动左指针
left++;
} else {
// 如果右边的线段较短,向左移动右指针
right--;
}
}
return area;
}
};
int main() {
Solution solution;
vector<int> height = {1, 8, 6, 2, 5, 4, 8, 3, 7};
cout << "最大水容量:" << solution.maxArea(height) << endl;
return 0;
}
Java
class Solution {
public int maxArea(int[] height) {
int area = 0;
int left = 0;
int right = height.length - 1;
while (left < right) {
int high = Math.min(height[left], height[right]); // 计算当前两条线段的最小高度
int wide = right - left; // 计算当前两条线段的宽度
area = Math.max(area, high * wide); // 计算当前容器的容量并更新最大值
if (height[left] < height[right]) {
// 如果左边的线段较短,向右移动左指针
left++;
} else {
// 如果右边的线段较短,向左移动右指针
right--;
}
}
return area;
}
}
public class Main {
public static void main(String[] args) {
Solution solution = new Solution();
int[] height = {1, 8, 6, 2, 5, 4, 8, 3, 7};
System.out.println("最大水容量:" + solution.maxArea(height));
}
}
Python
class Solution:
def maxArea(self, height):
area = 0
left = 0
right = len(height) - 1
while left < right:
high = min(height[left], height[right]) # 计算当前两条线段的最小高度
wide = right - left # 计算当前两条线段的宽度
area = max(area, high * wide) # 计算当前容器的容量并更新最大值
if height[left] < height[right]:
# 如果左边的线段较短,向右移动左指针
left += 1
else:
# 如果右边的线段较短,向左移动右指针
right -= 1
return area
if __name__ == "__main__":
solution = Solution()
height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
print("最大水容量:", solution.maxArea(height))