Victo

我的网络笔记本,用于收藏和总结一些知识。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::

1 题目描述

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (iai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (iai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 

示例:

输入: [1,8,6,2,5,4,8,3,7]
输出: 49

2 解题思路

2.1 暴力解析(结果正确但超时不通过)

  最简单的就是暴力解析,时间复杂度N*N

static const auto io_sync_off = []()
{
    // turn off sync
    std::ios::sync_with_stdio(false);
    // untie in/out streams
    std::cin.tie(nullptr);
    return nullptr;
}();

class Solution {
public:
    int maxArea(vector<int>& height) {
        int maxCap = 0;
        for (int i = 0; i < height.size() - 1; ++i) {
            for (int j = i + 1; j < height.size(); ++j) {
                int cap = (height[i] < height[j] ? height[i] : height[j]) * (j - i);
                if (cap > maxCap) {
                    maxCap = cap;
                }
            }
        }
        return maxCap;
    }
};

2.2 一趟归纳(效率最高)

  怎么在时间复杂度为N的情况下算出结果?我刚开始也想不到,看了别人的答案才明白的。思路是这样的:

  (1)类似于快排的思路,两个游标分别从两段进行判断;

  (2)比较两个游标位置大小,两者之间的“容量”是以较矮的一个值为准,计算出此时的容量与MAX值比对;

  (3)要想获得可能更大的容量,肯定是要游动较矮的游标,企图找到一个更高一些的组成新的容器;

  (4)迭代到两个游标相遇就结束了。

static const auto io_sync_off = []()
{
    // turn off sync
    std::ios::sync_with_stdio(false);
    // untie in/out streams
    std::cin.tie(nullptr);
    return nullptr;
}();

class Solution {
public:
    int maxArea(vector<int>& height) {
        int max = 0;
        for (int i = 0, j = height.size() - 1; i < j; ) {
            int minHeight = height[i] < height[j] ? height[i++] : height[j--];
            max = max > ((j - i + 1) * minHeight) ? max : ((j - i + 1) * minHeight);
        }
        return max;
    }
};

  

posted on 2019-03-28 15:41  VictoKu  阅读(193)  评论(0编辑  收藏  举报