LeetCode11 Container With Most Water

题意:

Given n non-negative integers a1a2, ..., an, where each represents a point at coordinate (iai). n vertical lines are drawn such that the two endpoints of line i is at (iai) 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.

 

分析:

自己做的时候脑子并不是很清楚(帮老板画图画的...),不过一步一步优化也算AC了。但是看着跑的时间那么高就知道肯定不是最优,

学习讨论区后知道了O(n)算法的思路并实现,思考历程记录如下:

1.暴力先写一个,把所有区间来一遍,O(n^2)。当然肯定超时...代码还是记录一下吧

 1 class Solution {
 2 public:
 3     int maxArea(vector<int>& height) {
 4         int result = 0;
 5         for (int i = 1; i < height.size(); ++i) {
 6             for (int j = 0; j < i; ++j) {
 7                 int h = i - j;
 8                 int l = min (height[i], height[j]);
 9                 result = max(result, h * l);
10             }
11         }
12         return result;
13     }
14 };

2. 不按照区间走,按照不同高度,高度依次向上时,找到符合该高度的最长区间(两头扫),然后比较。

高度用个map存,代码如下:(分析时间复杂度O(m*n*logm) m不同高度的数量),诸如1,2,3...15000全是不同高度数字的样例也会超时

class Solution {
public:
    int maxArea(vector<int>& height) {
        set<int> s;
        for (int i = 0; i < height.size(); ++i) {
            s.insert(height[i]);
        }
        auto itr = s.begin();
        int result = (*itr) * (height.size() - 1);
        for ( itr = s.begin(); itr != s.end(); ++itr) {
             int left = 0, right = height.size() - 1;
             while (height[left] < (*itr) ) {
                 ++left;
             }
             while (height[right] < (*itr) ) {
                 --right;
             }
             result = max(result, (right - left) * (*itr) );
        }
        return result;
    }
};

3.分析上述代码,其实left,right这里根本没必要每次都从头遍历。因为height是递增的,所以left,right在上一次基础上继续走即可。

所以代码内层只需一遍遍历,复杂度O(m*logm),这个可以AC了。

 1 class Solution {
 2 public:
 3     int maxArea(vector<int>& height) {
 4         set<int> s;
 5         for (int i = 0; i < height.size(); ++i) {
 6             s.insert(height[i]);
 7         }
 8         auto itr = s.begin();
 9         int result = 0;
10         int left = 0, right = height.size() - 1;  //这句优化!
11         for (itr = s.begin(); itr != s.end(); ++itr) {
12              while (height[left] < (*itr) ) {
13                  ++left;
14              }
15              while (height[right] < (*itr) ) {
16                  --right;
17              }
18              result = max(result, (right - left) * (*itr) );
19         }
20         return result;
21     }
22 };

4.实际上,也没有必要按照高度存储和遍历。

注意到如果从最大长度区间开始向内遍历,只有当高度更高时才有可能更新面积(因为长度已经比之前小),所以,两根指针一遍遍历即可。O(n)

代码:

 1 class Solution {
 2 public:
 3     int maxArea(vector<int>& height) {
 4         int i = 0, j = height.size() - 1, result = 0;
 5         while (i < j) {
 6             int minHeight = min(height[i], height[j]);
 7             result = max(result, minHeight * (j - i));
 8             while (height[i] <= minHeight) {
 9                 i++;
10             }
11             while (height[j] <= minHeight) {
12                 j--;
13             }
14         }
15         return result;
16     }
17 };

 

posted @ 2016-08-06 17:11  wangxiaobao1114  阅读(183)  评论(0编辑  收藏  举报