Leetcode第五题:用C++解决盛最多水的容器问题

1. 问题描述

我们首先看一下原题目:

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

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

输出:49

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

我们来分析一下这个题目:

给定一个数组,找出两个下标 ij,使得面积 (j - i) * min(height[i], height[j]) 最大。

根据木桶效应,如果把两条垂线看成两块木板,那么能容纳水的最大容量受限于较短的那根木板。


2. 解题思路

上面的面积公式告诉我们,我们要寻找的最大面积取决于两个因素,一个是底边的宽度,另一个是两个木板中较短的那一个。

最直观的解法还是两层for循环的暴力解法,但是这种 O( <math xmlns="http://www.w3.org/1998/Math/MathML"> n 2 n^2 </math>n2)的时间复杂度,在数据量过大时必然会导致超时。因此,我们需要寻找一种能够排除大量无效状态的方法。

这里,我们设置两个指针leftright,他们分别指向数组的最左边和最右边,此时,底边宽度是最长的,并且我们轻而易举就可以算出这种情况下的面积。

关键在于指针要怎么移动。

就拿上面那张图来举例,初始leftright指向的元素分别是 1 和 7 ,宽是 8,此时面积为 1 * 8 = 8。

假如我们移动比较长的木板,也就是现在right指向的数组元素,我们将right向左移动一位,这时宽减小为 7,而新得到的最短木板的高度绝不会超过上一次,并且可能还会小于上一次的。

因为left指向的元素1的限制,能容纳水的高度绝不会大于 1 ,所以对于left指向1 的这种情况来看,不论right怎么移,都不会得到比初始面积更大的值。原因很简单:因为宽度一定会变小,而高度可能不变,也可能变的更小,所以面积一定会变小。

排除了移动长木板的策略,下面我们应该尝试移动短木板。

对于初始状态,如果我们移动短木板,也就是left向右移动一位,底边宽度依然减小,但是不同的是新的高度有可能比上一次大。

因此,我们得到一个结论:只有移动较短的一块木板,才有可能在宽度不断减小的情况下,通过高度剧增从而让面积增加。


3. 完整代码实现

依据上面的解题思路,我们梳理一下算法流程:

  1. 初始化left = 0, right = n-1, max_area = 0
  2. left < right作为循环条件。
  3. 计算当前面积并更新面积最大值max_area
  4. 移动指针,若 height[left] < height[right],则 left++,否则right--。这里实现了每次都只改变较短的那块木板。
  5. 最后返回max_area

完整代码如下:

cpp 复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        //初始化双指针,分别指向最左端和最右端
        int left = 0;
        int right = height.size() - 1;
        int max_area = 0;
        while(left < right)
        {
            //计算当前面积
            int curr_area = (right - left) * min(height[left],height[right]);
            //更新最大面积
            max_area = max(curr_area,max_area);
            //移动指针
            (height[left]<height[right]) ? left++ : right--;
        }
        return max_area;
    }
};

这种实现,由于左右指针相向而行,每个元素只被访问一次,因此时间复杂度为 O(n)


本文结束。

相关推荐
张宏2363 小时前
原子操作 (基于Linux 应用层 C 语言)
linux
得物技术3 小时前
搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术
c++·后端·测试
kymjs张涛18 小时前
OpenClaw 学习小组:初识
android·linux·人工智能
程序设计实验室20 小时前
经历分享,发现挖矿木马后,服务器快速备份与重装(腾讯云平台)
linux
Miku161 天前
OpenClaw-Linux+飞书官方Plugin安装指南
linux·人工智能·agent
Miku161 天前
OpenClaw 接入 QQ Bot 完整实践指南
linux·人工智能·agent
xlp666hub1 天前
Leetcode 第三题:用C++解决最长连续序列
c++·leetcode
会员源码网1 天前
构造函数抛出异常:C++对象部分初始化的陷阱与应对策略
c++
xlp666hub1 天前
Leetcode第二题:用 C++ 解决字母异位词分组
c++·leetcode