双指针算法:最大盛水容器

暴力解法与其局限

11. 盛最多水的容器 - 力扣(LeetCode)

此题简单来说,就是给了一个数组,我们要将数组元素的值作为"墙",下标的距离为底,围成一个水缸,求得容积最大的那个。

先说暴力解法。

这很简单,容积等于底乘以高,给两个指针,依次遍历所有组合,依次求容积,每次更新容积最大的那个即刻,代码如下:

cpp 复制代码
int maxArea_bad(vector<int>& height) {
    //遍历组合
    int n = height.size();
    int v = 0;
    for (int i = 0; i < n; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            int w = j - i;//宽度
            int h = height[i] > height[j] ? height[j] : height[i];//高度
            if (v <= w * h)
            {
                v = w * h;
            }
        }
    }
    return v;
}

它的局限很明显------许多可排除的组合它都进行了遍历。

我们拿一个示例:

cpp 复制代码
h = [2, 8, 6, 2, 5, 4, 8, 3, 7]
     0  1  2  3  4  5  6  7  8

left此刻在0处,我们移动另一个指针right。

这时,你会发现,八个组合,每次用于计算的高都是left处的1,导致这些组合都被淘汰,原因很简单:容积的高受较矮的那个影响。

发现了这个就很好办了。

双指针优化

我们干脆把两个指针安排在两边,计算完了容积后,让较矮的那个移动往中间靠拢,不断更新容积。

比如组合(2,7)计算完后,更新更小的左边,left++,直接从(8,7)开始,因为如果计算(2,7)之间,底只会更短,而更新7那一边的话,就没有意义。比如,如果新的右边比左边更小,那容积会更小,如果比左边更大,那高度还是会依据左边。

这样一来,代码显而易见:

cpp 复制代码
int maxArea(vector<int>& height)
{
    int left = 0, right = height.size() - 1;
    int w = 0;//宽
    int v = 0;//体积
    while (left < right)
    {
        w = right - left;
        if (height[left] < height[right])
        {
            if (v < w * height[left])
            {
                v = w * height[left];
            }
            left++;
        }
        else
        {
            if (v < w * height[right])
            {
                v = w * height[right];
            }
            right--;
        }
    }

    return v;
}

当然,我们可以使用更加简洁的写法:

cpp 复制代码
int maxArea_better(vector<int>& height)
{
    int left = 0, right = height.size() - 1, ret = 0, v = 0;
    while (left < right)
    {
        v = (right - left) * (height[left] < height[right] ? height[left++] : height[right--]);
        ret = max(ret, v);
    }
    return ret;
}
相关推荐
小小龙学IT2 小时前
三菱 PLC MC 协议(SLMP / QnA 兼容 3E 帧)深度解析:从帧结构到 C++/Go 双语言采集实战
c语言·c++·golang
程序猿编码3 小时前
C++/CUDA 手写 LLM 推理引擎:拆解 vLLM 核心 PagedAttention 与连续批处理
开发语言·c++·深度学习·神经网络·推理·vllm
hold?fish:palm3 小时前
44 二叉搜索树中第K小的元素
开发语言·c++·算法
凉茶钱3 小时前
【吃透C++】万字解析类和对象
开发语言·c++
白杨尚青3 小时前
C++入门篇(十):string(上)——认识string:构造与三大遍历(一条龙讲透operator[]、迭代器、auto、范围for)
java·开发语言·c++·笔记·stl
FlightYe3 小时前
视界原理之2D视频(二):视频文件里有什么
android·linux·网络·c++·ffmpeg·音视频·aac
Chen—LSN3 小时前
C语言——⽂件操作(1)
c语言·开发语言·c++·经验分享·笔记·算法·链表
anew___4 小时前
《从零手写操作系统 (11):文件系统初探——initrd与VFS抽象层》
java·javascript·算法
辛苦才能4 小时前
C++ map/set 深度解析:从关联式容器的本质到 operator[] 的三重身份
开发语言·c++