原题:
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.
Note: You may not slant the container and n is at least 2.
解法:
开始试着用暴力的O(n^2)去做,当然既然是medium水平的题目也不会这么简单,不过这题的思路是很直接的,秉承着尽量不看解答的原则,这个解法是我自己想到的,可能有更快的解法。
这题的一个要点就是我们要短的那条木板决定了容器的高度,所以只要当我们选择了一个木板的时候,这个木板一定是最短的就可以了,顺利地想到可以降序排序,排序后找到的木板一定是最短的。
那么问题来了,有了高度,怎么确定两个木板的距离的?也很简单,我们在排序的时候记录下标就可以了。但是我们要找到和当前的木板下标最远的那个,怎么办呢?很简单,和第k+1个木板相距最远的木板应该是前k个比较高木板的最大x坐标或者最小x坐标,遍历过程中一直做一下记录就可以了。
最后的时间复杂度是O(nlogn+n)=O(nlogn),如果你自己写桶排序的话当然也可以O(n),总之就是排序的复杂度,题目给的也就是O(nlogn),归并排序就可以,快排的话,感觉最差情况下会超时。
STL里的algorithm有很多好用的函数(最近刷题的过程中真的感受到了STL的方便之处),sort可以做到O(nlogn)排序,max/min可以直接找最大容量和最大、最小下标。我偷懒在网上找了段可以记录索引值的排序算法,也可以参考一下。
下面是代码:
template <typename T>
vector<int> sort_indexes(const vector<T> &v) {
// 初始化索引向量
vector<int> idx(v.size());
for (int i = 0; i < v.size(); i++)
{
idx[i] = i;
}
// 通过比较v的值对索引idx进行排序
sort(idx.begin(), idx.end(),
[&v](size_t i1, size_t i2) {return v[i1] > v[i2]; });
return idx;
}
class Solution {
public:
int maxArea(vector<int>& height) {
int max_area = 0;
int len = height.size();
if (len == 0)
{
return 0;
}
vector<int> idx = sort_indexes(height);
int min_x = idx[0], max_x = idx[0];
for (int i = 0; i < len; i++)
{
max_area = max(max_area, (int)max(fabs(idx[i] - min_x - 0.0)*height[idx[i]], fabs(idx[i] - max_x - 0.0)*height[idx[i]]));
max_x = max(max_x, idx[i]);
min_x = min(min_x, idx[i]);
}
return max_area;
}
};