当前位置: 首页 > article >正文

【5.2】指针算法-双指针求盛最多水的容器

一、题目

        给你 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 ]
输出: 4 9

二、解题思路

双指针求解思路:

        这种题最容易想到的是暴力求解,即计算每两个柱子所围成的面积,将所有可能的面积计算一遍,然后保留最大值。然而,暴力求解的效率通常不高,因此我们尝试其他方法。下面我们来试试双指针求解。根据木桶原理,桶的容量由最短的木板决定,因此这里矩形的高度也是由最矮的柱子决定的。我们可以使用两个指针,一个`left`指向左边的柱子,以其高度为矩形的高度,然后从最右边开始往左扫描,找到比`left`柱子高的柱子为止(如果没找到,那么矩形的宽度就是0)。计算矩形面积之后,`left`再往右移一位,以同样的方式继续查找……。

        例如,在下图中,计算以第1个柱子的高度为矩形的高度,因为高度一定,要想使矩形的面积最大,就只能是矩形的宽度最大,所以这里从数组的最后面开始找,找到一个比3大或等于3的值即可,如果没找到那么宽度就是0。

        为了防止遗漏,我们在查找时不仅从前面开始找,还要从后面开始找,需要进行两遍查找。代码如下:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int maxArea(vector<int>& height) {
    int maxarea = 0, left = 0, length = height.size();
    int area;
    int right;

    // 从前面开始找
    while (left < length) {
        right = length - 1;
        while (right > left) {
            if (height[right] < height[left]) {
                right--;
            } else {
                break;
            }
        }
        // 计算矩形的面积
        area = height[left] * (right - left);
        // 保存计算过的最大的面积
        maxarea = max(maxarea, area);
        left++;
    }

    // 从后面开始找,和上面类似
    right = length - 1;
    while (right > 0) {
        left = 0;
        while (right > left) {
            if (height[right] > height[left]) {
                left++;
            } else {
                break;
            }
        }
        area = height[right] * (right - left);
        maxarea = max(maxarea, area);
        right--;
    }

    return maxarea;
}

int main() {
    vector<int> height = {1, 8, 6, 2, 5, 4, 8, 3, 7};
    int result = maxArea(height);
    cout << "The maximum area is: " << result << endl;
    return 0;
}

        上面的代码我们两个方向都要查找,是不是有点繁琐?我们再认真看下这个图:

        当我们以3作为矩形的高度,从最右边开始向左寻找宽度时,我们会停止搜索直到找到一个高度大于3的柱子为止。在这个例子中,我们找到了高度为4的柱子。因此,从第3根柱子到第4根柱子之间的矩形区域的高度就是第3根柱子的高度。如果我们从右向左搜索时遇到的柱子高度小于3,比如这里是2,那么我们实际上找到了以2为高度的矩形的最大面积。这意味着我们可以将从左到右和从右到左的搜索过程合并成一个,从而使代码变得非常简洁。让我们来看看具体是如何实现的。

三、代码实现

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int maxArea(vector<int>& height) {
    int maxarea = 0, left = 0, right = height.size() - 1;
    int area = 0;

    while (left < right) {
        // 计算面积,面积等于宽*高,宽就是left和right之间的距离,高就是
        // left和right所对应的最低高度
        area = min(height[left], height[right]) * (right - left);
        // 保存计算过的最大的面积
        maxarea = max(maxarea, area);
        // 柱子矮的往中间靠
        if (height[left] < height[right])
            left++;
        else
            right--;
    }

    return maxarea;
}

int main() {
    vector<int> height = {1, 8, 6, 2, 5, 4, 8, 3, 7};
    int result = maxArea(height);
    cout << "The maximum area is: " << result << endl;
    return 0;
}


http://www.kler.cn/news/366437.html

相关文章:

  • vivado 器件电源因素与系统关联性
  • PHP+REDIS设置请求限流(设置1秒内最大请求数1000QPS)
  • 【计算机网络 - 基础问题】每日 3 题(五十七)
  • 《在1688的数字海洋中,如何用API网罗一家店铺的所有商品?》
  • Python与MySQL
  • 【在Win11下安装ubuntu +图形化界面】
  • 如何对群辉docker进行简单更新升级
  • MATLAB中的fftshift函数
  • kubeadm快速自动化部署k8s集群
  • (三)第一个Qt程序“Qt版本的HelloWorld”
  • jmeter录制接口
  • 【初阶数据结构】计数排序 :感受非比较排序的魅力
  • Flink CDC系列之:学习理解核心概念——Data Pipeline
  • MySQL 二进制和中继日志管理
  • STM32L031F6P6开发环境搭建
  • 隨筆 20241023 Kafka 的幂等性与分区顺序性探讨
  • excel斜线表头
  • python爬虫:实例讲解xpatch的基本使用
  • 人工智能在自然语言处理(NLP)中的应用
  • Redis面试题扩展
  • .NET Core WebApi第2讲:前后端分离,Restful
  • unity URP下VolumetricFog插件发布的时候安卓里没有显示问题
  • C++二级2021年9月试卷及答案
  • Python——脚本实现datax全量同步mysql到hive
  • (北京政务服务满意度公司)满意度调查助力服务质量提升
  • 【Java】类来管理个人简历信息