容器盛水问题(NC128/考察次数Top39/难度中等)

Posted 码农指南

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了容器盛水问题(NC128/考察次数Top39/难度中等)相关的知识,希望对你有一定的参考价值。

描述:
给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个容器,请返回容器能装多少水。
在这里插入图片描述
示例1
输入:
[3,1,2,5,2,4]
返回值:
5
(题目来自牛客网)

用C++实现如下

class Solution {
public:
    /**
     * max water
     * @param arr int整型vector the array
     * @return long长整型
     */
    long long maxWater(vector<int>& arr) {
        // write code here
        
//         //思路1,使用暴力法进行求解,求解出每个位置上方的水量,然后累加起来(一般会出现超时的情况)
//         int n = arr.size();
//         if(n<=2)
//             return 0;
//         int maxwater=0;
//         for(int i=1; i<arr.size()-1; ++i)                 //由于0位置上和n-1位置上一定没有水,不用遍历
//         {
//             int leftmax=0;
//             int rightmax=0;
//             for(int j=0;j<i;j++)                          //遍历i左侧的最大值
//             {
//                 leftmax=leftmax<arr[j]?arr[j]:leftmax;
//             }
//             for(int k=i+1;k<=arr.size()-1;++k)            //遍历i右侧的最大值
//             {
//                 rightmax=rightmax<arr[k]?arr[k]:rightmax;
//             }
//             //因为arr[i]很大时,min(leftmax,rightmax)-arr[i]小于0
//             maxwater=maxwater+max(0,min(leftmax,rightmax)-arr[i]);
//         }
//         return maxwater;
        
        //思路2,空间换时间法,先用构建左右最大值数组(与上面的不同点在于,上面每个i都要进行求解,而此方法只用干一次就存起来)
        int n = arr.size();
        if (n <= 2)
            return 0;
        long maxwater=0;
        long leftmax[arr.size()];                                       //定义i位置左边的最大值
        long rightmax[arr.size()];                                      //定义i位置右边的最小值
        leftmax[0] = arr[0];
        rightmax[arr.size()-1] = arr[arr.size()-1];                     //特殊时候,其它时候用遍历进行解决
        
        for(int i=1; i<arr.size(); i++)                                 //遍历进行赋值
        {
            leftmax[i]=max(leftmax[i-1],(long)arr[i]);
        }
        for(int j=arr.size()-2;j>0; j--)                                //遍历进行赋值
        {
            rightmax[j]=max(rightmax[j+1],(long)arr[j]);
        }
        
        for(int k=1; k<arr.size()-1; k++)                               //求解,然后再累加起来
        {
            maxwater=maxwater+max((long)0, min(leftmax[k],rightmax[k])-(long)arr[k]);
        }
        return maxwater;
        
        
        //思路3
//         int n = arr.size();
//         if (n <= 2)
//             return 0;
//         long long res = 0;
//         stack<int> high_rec;
//         high_rec.push(0);
//         for (int i=1;i<n;++i)
//         {
//             if (arr[i] <= arr[i-1])
//             {
//                 if (arr[i] == arr[i-1])
//                     high_rec.pop();
//                 high_rec.push(i);
//                 continue;
//             }
//             int cur = arr[i-1];
//             while (!high_rec.empty())
//             {
//                 int j = high_rec.top();
//                 long long a = (i - j - 1), b;
//                 if (arr[j] <= arr[i])
//                 {
//                     b = (arr[j] - cur);
//                     res += a * b;
//                     cur = arr[j];
//                     high_rec.pop();
//                 }
//                 else {
//                     b = (arr[i] - cur);
//                     res += a * b;
//                     break;
//                 }
//             }
//             high_rec.push(i);
//         }
//         return res;
    }
};

纯手撕代码,如果觉得内容不错麻烦点个赞,后面陆续配上Top100算法题通俗易懂的讲解视频,可以花两个月时间完全掌握,进大厂不是梦,转行狗亲测!

以上是关于容器盛水问题(NC128/考察次数Top39/难度中等)的主要内容,如果未能解决你的问题,请参考以下文章

斐波那契数列(NC65/考察次数Top28/难度入门)

跳台阶(NC68/考察次数Top11/难度简单)

合并区间(NC37/考察次数Top57/难度中等)

合并区间(NC37/考察次数Top57/难度中等)

最长公共前缀(NC55/考察次数Top64/难度简单)

最长公共前缀(NC55/考察次数Top64/难度简单)