C++收集雨水问题怎么解决(C++,编程语言)

时间:2024-04-28 11:59:54 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

这篇“C++收集雨水问题怎么解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++收集雨水问题怎么解决”文章吧。

收集雨水

Givennnon-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

C++收集雨水问题怎么解决

The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.Thanks Marcosfor contributing this image!

Example:

Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

这道收集雨水的题跟之前的那道Largest Rectangle in Histogram有些类似,但是又不太一样,先来看一种方法,这种方法是基于动态规划 Dynamic Programming 的,维护一个一维的 dp 数组,这个 DP 算法需要遍历两遍数组,第一遍在 dp[i] 中存入i位置左边的最大值,然后开始第二遍遍历数组,第二次遍历时找右边最大值,然后和左边最大值比较取其中的较小值,然后跟当前值 A[i] 相比,如果大于当前值,则将差值存入结果,参见代码如下:

C++ 解法一:

classSolution{public:inttrap(vector<int>&height){intres=0,mx=0,n=height.size();vector<int>dp(n,0);for(inti=0;i<n;++i){dp[i]=mx;mx=max(mx,height[i]);}mx=0;for(inti=n-1;i>=0;--i){dp[i]=min(dp[i],mx);mx=max(mx,height[i]);if(dp[i]>height[i])res+=dp[i]-height[i];}returnres;}};

Java 解法一:

publicclassSolution{publicinttrap(int[]height){intres=0,mx=0,n=height.length;int[]dp=newint[n];for(inti=0;i<n;++i){dp[i]=mx;mx=Math.max(mx,height[i]);}mx=0;for(inti=n-1;i>=0;--i){dp[i]=Math.min(dp[i],mx);mx=Math.max(mx,height[i]);if(dp[i]-height[i]>0)res+=dp[i]-height[i];}returnres;}}

再看一种只需要遍历一次即可的解法,这个算法需要 left 和 right 两个指针分别指向数组的首尾位置,从两边向中间扫描,在当前两指针确定的范围内,先比较两头找出较小值,如果较小值是 left 指向的值,则从左向右扫描,如果较小值是 right 指向的值,则从右向左扫描,若遇到的值比当较小值小,则将差值存入结果,如遇到的值大,则重新确定新的窗口范围,以此类推直至 left 和 right 指针重合,参见代码如下:

C++ 解法二:

classSolution{public:inttrap(vector<int>&height){intres=0,l=0,r=height.size()-1;while(l<r){intmn=min(height[l],height[r]);if(mn==height[l]){++l;while(l<r&&height[l]<mn){res+=mn-height[l++];}}else{--r;while(l<r&&height[r]<mn){res+=mn-height[r--];}}}returnres;}};

Java 解法二:

publicclassSolution{publicinttrap(int[]height){intres=0,l=0,r=height.length-1;while(l<r){intmn=Math.min(height[l],height[r]);if(height[l]==mn){++l;while(l<r&&height[l]<mn){res+=mn-height[l++];}}else{--r;while(l<r&&height[r]<mn){res+=mn-height[r--];}}}returnres;}}

我们可以对上面的解法进行进一步优化,使其更加简洁:

C++ 解法三:

classSolution{public:inttrap(vector<int>&height){intl=0,r=height.size()-1,level=0,res=0;while(l<r){intlower=height[(height[l]<height[r])?l++:r--];level=max(level,lower);res+=level-lower;}returnres;}};

Java 解法三:

publicclassSolution{publicinttrap(int[]height){intl=0,r=height.length-1,level=0,res=0;while(l<r){intlower=height[(height[l]<height[r])?l++:r--];level=Math.max(level,lower);res+=level-lower;}returnres;}}

其实用 stack 的方法博主感觉更容易理解,思路是,遍历高度,如果此时栈为空,或者当前高度小于等于栈顶高度,则把当前高度的坐标压入栈,注意这里不直接把高度压入栈,而是把坐标压入栈,这样方便在后来算水平距离。当遇到比栈顶高度大的时候,就说明有可能会有坑存在,可以装雨水。此时栈里至少有一个高度,如果只有一个的话,那么不能形成坑,直接跳过,如果多余一个的话,那么此时把栈顶元素取出来当作坑,新的栈顶元素就是左边界,当前高度是右边界,只要取二者较小的,减去坑的高度,长度就是右边界坐标减去左边界坐标再减1,二者相乘就是盛水量啦,参见代码如下:

C++ 解法四:

classSolution{public:inttrap(vector<int>&height){stack<int>st;inti=0,res=0,n=height.size();while(i<n){if(st.empty()||height[i]<=height[st.top()]){st.push(i++);}else{intt=st.top();st.pop();if(st.empty())continue;res+=(min(height[i],height[st.top()])-height[t])*(i-st.top()-1);}}returnres;}};

Java 解法四:

classSolution{publicinttrap(int[]height){Stack<Integer>s=newStack<Integer>();inti=0,n=height.length,res=0;while(i<n){if(s.isEmpty()||height[i]<=height[s.peek()]){s.push(i++);}else{intt=s.pop();if(s.isEmpty())continue;res+=(Math.min(height[i],height[s.peek()])-height[t])*(i-s.peek()-1);}}returnres;}}

以上就是关于“C++收集雨水问题怎么解决”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

本文:C++收集雨水问题怎么解决的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:怎么用C++求直方图中最大的矩形下一篇:

17 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18