[leetcode] Container With Most Water


Container With Most Water

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.

tag:

9/26/2015 update

class Solution {
public:
    int maxArea(vector<int>& height) {
        if(height.size() < 2) return 0;
        int i = 0;
        int j = height.size() - 1;
        int ans = 0;
        while(i < j){
            int thisAns = min(height[i], height[j]) * (j - i);
            ans = ans < thisAns? thisAns: ans;
            if(height[i] < height[j]){
                i++;
            }
            else{
                j--;
            }
        }
        return ans;
    }
};

 

暴力搜,o(n^2)超时。

class Solution {
public:
    int maxArea(vector<int> &height) {
        int maxCapacity = 0;
        for(vector<int>::iterator start = height.begin(); start != height.end(); start++){
            for(vector<int>::iterator end = start + 1; end != height.end(); end++){
                int minHeight = min(*start, *end);
                int thisCapacity = minHeight * distance(start, end);
                if (thisCapacity > maxCapacity){
                    maxCapacity = thisCapacity;
                }
            }
        }
        return maxCapacity;
    }
};

先排序,然后剪枝。最坏情况o(n^2),不幸test case中有最坏情况(1, 2, 3, 4, 5, 6…)超时。

class point{
public:
    int height;
    int x;
    point(int x, int h) : x(x), height(h){}
};
class Cmp{
public:
  bool operator()(point a, point b){
      return a.x > b.x;
  }  
};
class Solution {
public:
    int maxArea(vector<int> &height) {
        int maxCapacity = 0;
        vector<point> data;
        for(int i = 0; i < height.size(); i++){
            data.push_back(point(i, height[i]));
        }
        sort(data.begin(), data.end(), Cmp());
        for(vector<point>::iterator start = data.begin(); start != data.end(); start++){
            if((*start).height * max((int)(data.size() - (*start).x - 1), (*start).x) < maxCapacity){
                return maxCapacity;
            }
            for(vector<point>::iterator end = start + 1; end != data.end(); end++){
                if((*end).height * max((int)(data.size() - (*end).x - 1), (*end).x) < maxCapacity){
                    break;
                }
                int minHeight = min((*start).height, (*end).height);
                int thisCapacity = minHeight * distance(start, end);
                if (thisCapacity > maxCapacity){
                    maxCapacity = thisCapacity;
                }
            }
        }
        return maxCapacity;
    }
};

再次优化,这题和直方图中最大矩形的那道题很类似。

我用left储存原数组中左到右递增的序列,用right储存原数组中从右到左递增的序列。在两个数组中遍历。

最坏情况o(n^2)。AC了。

class node{
public:
   int x;
   int height;
   node(int x, int h): x(x), height(h){}
};
class Solution {
public:
    int maxArea(vector<int> &height) {
        int maxCapacity = 0;
        vector<node > left;
        vector<node > right;
        int length = height.size();
        left.push_back(node(0, height[0]));
        right.push_back(node(length - 1, height[length - 1]));
        for(int i = 0; i < length; i++){
            if(left.back().height < height[i]){
                left.push_back(node(i, height[i]));
            }
            if(right.back().height < height[length - i - 1]){
                right.push_back(node(length - i - 1, height[length - i - 1]));
            }
        }
        for(int i = 0; i < left.size(); i++){
            int idxl = left[i].x;
            for(int j = 0; j < right.size(); j++){
                int idxr = right[j].x;
                if(idxr <= idxl){
                    break;
                }
                int thisCapacity = min(left[i].height, right[j].height) * (idxr - idxl);
                if(thisCapacity > maxCapacity){
                    maxCapacity = thisCapacity;
                }
            }
        }
        return maxCapacity;
    }
};

 

但是看了解答,其实有更好的o(n)的方法。

维护两个指针,一个放在数组开头,一个放在数组末尾。

两个指针都向中间靠拢,每次移动height小的那个指针。因为height小的是影响盛水量的瓶颈。

class Solution {
public:
    int maxArea(vector<int> &height) {
        int maxCapacity = 0;
        int start = 0;
        int end = height.size() - 1;
        while(start < end){
            int minHeight = min(height[start], height[end]);
            int thisCapacity = minHeight * (end - start);
            if (thisCapacity > maxCapacity){
                maxCapacity = thisCapacity;
            }
            if(minHeight == height[start]){
                start++;
            }
            else{
                end--;
            }
        }
        return maxCapacity;
    }
};

Selection_014

 

 

Leave a comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.