题目链接:
https://leetcode.com/problems/container-with-most-water/description/
题目描述:
Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
给定n个非负整数a1,a2,...,an,其中每个表示坐标(i,ai)处的点。 绘制n条垂直线,使得线i的两个端点在(i,ai)和(i,0)处。 找到两条线,它们与x轴一起形成一个容器,使得容器含有最多的水。
对于这样的问题,自然而然的想到最naive的一种解法,即遍历任意两条直线段围成的面积,找到最大值。
class Solution {
public:
int maxArea(vector<int>& height) {
int m_areas = 0;
int s = height.size();
for (int i = 0; i < s - 1; i++) {
for (int j = i + 1; j < s; j++) {
int area = min(height[i], height[j]) * (j - i);
m_areas = (m_areas < area) ? area : m_areas;
}
}
return m_areas;
}
int min(int a, int b) {
return (a < b) ? a : b;
}
};
但是很显然,一个medium难度的题没有这么简单,基于O(n^2)的时间复杂度导致了这道题的超时。
而在网站所给的solution中,提供了一种时间复杂度只有O(n)的优雅的解法。
这种解法是从输入的线段中从头和尾向中间遍历(这样能够得到最长的宽),线段的长度作为比较条件,较长的线段保留,较短的线段向中间查找,遍历整个数组后就能得到最大的面积。以下是根据答案提供的思路写下的代码:
class Solution {
public:
int maxArea(vector<int>& height) {
int m_area = 0, l = 0, r = height.size() - 1;
while (l < r) {
int area = comp(height[l] , height[r], false) * (r - l);
m_area = comp(area, m_area, true);
if (height[l] < height[r]) l++;
else r--;
}
return m_area;
}
int comp(int a, int b, bool i) {
if (i) return (a > b) ? a : b;
else return (a < b) ? a : b;
}
};
代码提交结果运行时间很短