开发者社区> Cool架构> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Cool说丨力扣11

简介: 11. 盛最多水的容器
+关注继续查看

11. 盛最多水的容器

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (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

第一版,速度太慢

   int maxArea(vector<int>& height) {

   int len=height.size();

    int mostWater = 0;

    for (int i = 0,row,col; i < len; ++i)

    {

        for (int j = i+1; j < len; ++j

        {

            row = j - i;

            col = min(height[i], height[j]);

            mostWater = row * col > mostWater ? row * col : mostWater;

        }

    }

    return mostWater;  

   }

执行用时 :1640 ms, 在所有 C++ 提交中击败了9.51%的用户

内存消耗 :9.9 MB, 在所有 C++ 提交中击败了65.57%的用户

第二版 双指针,很快

   int maxArea(vector<int>& height) {

    int high=height.size()-1,low=0;

    int mostWater = 0,temp;

    while (low < high)

    {

        temp = (high - low) * min(height[low], height[high]);

        mostWater = mostWater > temp ? mostWater : temp;

        if (height[low] <= height[high]) low++;

        else high--;

    }

    return mostWater;

   }

执行用时 :16 ms, 在所有 C++ 提交中击败了97.32%的用户

内存消耗 :9.8 MB, 在所有 C++ 提交中击败了74.86%的用户

官方题解:

https://leetcode-cn.com/problems/container-with-most-water/solution/sheng-zui-duo-shui-de-rong-qi-by-leetcode/

最初我们考虑由最外围两条线段构成的区域。现在,为了使面积最大化,我们需要考虑更长的两条线段之间的区域。如果我们试图将指向较长线段的指针向内侧移动,矩形区域的面积将受限于较短的线段而不会获得任何增加。但是,在同样的条件下,移动指向较短线段的指针尽管造成了矩形宽度的减小,但却可能会有助于面积的增大。因为移动较短线段的指针会得到一条相对较长的线段,这可以克服由宽度减小而引起的面积减小。

比较经典的介绍

思路:算法流程: 设置双指针 ii,jj 分别位于容器壁两端,根据规则移动指针(后续说明),并且更新面积最大值 res,直到 i == j 时返回 res。

指针移动规则与证明: 每次选定围成水槽两板高度 h[i]h[i],h[j]h[j] 中的短板,向中间收窄 11 格。以下证明:

设每一状态下水槽面积为 S(i, j)S(i,j),(0 <= i < j < n)(0<=i<j<n),由于水槽的实际高度由两板中的短板决定,则可得面积公式 S(i, j) = min(h[i], h[j]) × (j - i)S(i,j)=min(h[i],h[j])×(j−i)。在每一个状态下,无论长板或短板收窄 11 格,都会导致水槽 底边宽度 -1−1:若向内移动短板,水槽的短板 min(h[i], h[j])min(h[i],h[j]) 可能变大,因此水槽面积 S(i, j)S(i,j) 可能增大。若向内移动长板,水槽的短板 min(h[i], h[j])min(h[i],h[j]) 不变或变小,下个水槽的面积一定小于当前水槽面积。因此,向内收窄短板可以获取面积最大值。换个角度理解:若不指定移动规则,所有移动出现的 S(i, j)S(i,j) 的状态数为 C(n, 2)C(n,2),即暴力枚举出所有状态。在状态 S(i, j)S(i,j) 下向内移动短板至 S(i + 1, j)S(i+1,j)(假设 h[i] < h[j]h[i]<h[j] ),则相当于消去了 {S(i, j - 1), S(i, j - 2), ... , S(i, i + 1)}S(i,j−1),S(i,j−2),...,S(i,i+1) 状态集合。而所有消去状态的面积一定 <= S(i, j)<=S(i,j):短板高度:相比 S(i, j)S(i,j) 相同或更短(<= h[i]<=h[i]);底边宽度:相比 S(i, j)S(i,j) 更短。因此所有消去的状态的面积都 < S(i, j)<S(i,j)。通俗的讲,我们每次向内移动短板,所有的消去状态都不会导致丢失面积最大值 。复杂度分析:

时间复杂度 O(N)O(N),双指针遍历一次底边宽度 NN 。空间复杂度 O(1)O(1),指针使用常数额外空间。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Cool说丨力扣69
[69. x 的平方根](https://leetcode-cn.com/problems/sqrtx/)
16 0
Cool说丨力扣153、454
153. 寻找旋转排序数组中的最小值 454. 四数相加 II
31 0
Cool说丨力扣6
6. Z 字形变换
15 0
Cool说丨力扣29/34
关注博主。获取更多知识
15 0
Cool说丨力扣165
[165. 比较版本号](https://leetcode-cn.com/problems/compare-version-numbers/)
13 0
Cool说丨力扣347
[347. 前 K 个高频元素]
15 0
Cool说丨力扣350
[350. 两个数组的交集 II](https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/)
16 0
Cool说丨力扣414与581
414. 第三大的数 581. 最短无序连续子数组
17 0
Cool说丨力扣17
17. 电话号码的字母组合
12 0
+关注
Cool架构
大三在读,两次国奖,竞赛生。
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载