本题是Bloomberg的面试题。
问题描述:
一、第一种方法-暴力解法
当我们在面试时想不到解题的方法时,不妨使用暴力解法,双重遍历数组。
当 i = 0 时,使用指针 j 遍历数组,找到第一轮的最大值 area:
当i = 2 ,使用指针 j 遍历数组,找到第二轮的最大值 area:
直到 指针 i 遍历完成。
实现代码:
class Solution {
public:
int maxArea(vector<int>& height) {
assert(height.size() >= 2);
int area = 0;
for(int i = 0 ; i < height.size() ; i ++)
for(int j = i + 1; j < height.size() ; j ++)
area = max(area , min(height[i], height[j]) * (j - i));
return area;
}
};
时间复杂度:O(n^2)
空间复杂度:O(1)
第二种方法:对撞指针法
分别在头、尾元素定义两个指针 l , r ;
如图所示,遍历数组,直到两个指针相遇,停止循环
实现代码:
/// Two Pointers
/// Time Complexity: O(n)
/// Space Complexity: O(1)
class Solution {
public:
int maxArea(vector<int>& height) {
assert(height.size() >= 2);
int l = 0, r = height.size() - 1;
int area = 0;
while(l < r){
area = max(area , min(height[l], height[r]) * (r - l));
if(height[l] < height[r])
l ++;
else
r --;
}
return area;
}
};
第三种方法:对撞指针法的优化
首先,使用第一个和最后一行来评估最宽的容器。所有其他可能的容器都不那么宽,所以要有更多的水,它们需要更高。因此,在评估了最宽的容器之后,在两端都跳过不支持更高高度的线。然后评估我们到达的新容器。重复,直到不再有可能的容器。
实现代码:
int maxArea(vector<int>& height) {
int water = 0;
int i = 0, j = height.size() - 1;
while (i < j) {
int h = min(height[i], height[j]);
water = max(water, (j - i) * h);
while (height[i] <= h && i < j) i++;
while (height[j] <= h && i < j) j--;
}
return water;
}
分析:
① i = 0, j = 9
water = 1 * (9 - 0) = 9;
i ++; j 不变;
② i = 1, j = 8;
water = max(49, 7 * 7) = 49;
然后 j--;
③ i = 1, j = 7;
water = max(49, 3 * 6) = 49;
然后 j -- ;
④ i = 1, j =6;
water = max(49, 5 * 8) = 49;
然后 j -- ;
⑤ i = 2, j =5;
water = max(49, 3 * 4) = 49;
然后 j -- ;
⑥ i = 2, j =4;
water = max(49, 2 * 5) = 49;
然后 j -- ;
⑦ i = 2, j =3;
water = max(49, 2 * 1) = 49;
然后 j -- ;
两个指针相遇,完成整个遍历过程。
参考资料: