本篇內(nèi)容介紹了“C++怎么實(shí)現(xiàn)收集雨水”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
十余年的平羅網(wǎng)站建設(shè)經(jīng)驗(yàn),針對設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。網(wǎng)絡(luò)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整平羅建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“平羅網(wǎng)站設(shè)計(jì)”,“平羅網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
Given n non-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.
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 Marcos for contributing this image!
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
這道收集雨水的題跟之前的那道 Largest Rectangle in Histogram 有些類似,但是又不太一樣,先來看一種方法,這種方法是基于動(dòng)態(tài)規(guī)劃 Dynamic Programming 的,維護(hù)一個(gè)一維的 dp 數(shù)組,這個(gè) DP 算法需要遍歷兩遍數(shù)組,第一遍在 dp[i] 中存入i位置左邊的最大值,然后開始第二遍遍歷數(shù)組,第二次遍歷時(shí)找右邊最大值,然后和左邊最大值比較取其中的較小值,然后跟當(dāng)前值 A[i] 相比,如果大于當(dāng)前值,則將差值存入結(jié)果,參見代碼如下:
C++ 解法一:
class Solution { public: int trap(vector<int>& height) { int res = 0, mx = 0, n = height.size(); vector<int> dp(n, 0); for (int i = 0; i < n; ++i) { dp[i] = mx; mx = max(mx, height[i]); } mx = 0; for (int i = 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]; } return res; } };
Java 解法一:
public class Solution { public int trap(int[] height) { int res = 0, mx = 0, n = height.length; int[] dp = new int[n]; for (int i = 0; i < n; ++i) { dp[i] = mx; mx = Math.max(mx, height[i]); } mx = 0; for (int i = 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]; } return res; } }
再看一種只需要遍歷一次即可的解法,這個(gè)算法需要 left 和 right 兩個(gè)指針分別指向數(shù)組的首尾位置,從兩邊向中間掃描,在當(dāng)前兩指針確定的范圍內(nèi),先比較兩頭找出較小值,如果較小值是 left 指向的值,則從左向右掃描,如果較小值是 right 指向的值,則從右向左掃描,若遇到的值比當(dāng)較小值小,則將差值存入結(jié)果,如遇到的值大,則重新確定新的窗口范圍,以此類推直至 left 和 right 指針重合,參見代碼如下:
C++ 解法二:
class Solution { public: int trap(vector<int>& height) { int res = 0, l = 0, r = height.size() - 1; while (l < r) { int mn = 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--]; } } } return res; } };
Java 解法二:
public class Solution { public int trap(int[] height) { int res = 0, l = 0, r = height.length - 1; while (l < r) { int mn = 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--]; } } } return res; } }
我們可以對上面的解法進(jìn)行進(jìn)一步優(yōu)化,使其更加簡潔:
C++ 解法三:
class Solution { public: int trap(vector<int>& height) { int l = 0, r = height.size() - 1, level = 0, res = 0; while (l < r) { int lower = height[(height[l] < height[r]) ? l++ : r--]; level = max(level, lower); res += level - lower; } return res; } };
Java 解法三:
public class Solution { public int trap(int[] height) { int l = 0, r = height.length - 1, level = 0, res = 0; while (l < r) { int lower = height[(height[l] < height[r]) ? l++ : r--]; level = Math.max(level, lower); res += level - lower; } return res; } }
下面這種解法是用 stack 來做的,博主一開始都沒有注意到這道題的 tag 還有 stack,所以以后在總結(jié)的時(shí)候還是要多多留意一下標(biāo)簽啊。其實(shí)用 stack 的方法博主感覺更容易理解,思路是,遍歷高度,如果此時(shí)棧為空,或者當(dāng)前高度小于等于棧頂高度,則把當(dāng)前高度的坐標(biāo)壓入棧,注意這里不直接把高度壓入棧,而是把坐標(biāo)壓入棧,這樣方便在后來算水平距離。當(dāng)遇到比棧頂高度大的時(shí)候,就說明有可能會(huì)有坑存在,可以裝雨水。此時(shí)棧里至少有一個(gè)高度,如果只有一個(gè)的話,那么不能形成坑,直接跳過,如果多余一個(gè)的話,那么此時(shí)把棧頂元素取出來當(dāng)作坑,新的棧頂元素就是左邊界,當(dāng)前高度是右邊界,只要取二者較小的,減去坑的高度,長度就是右邊界坐標(biāo)減去左邊界坐標(biāo)再減1,二者相乘就是盛水量啦,參見代碼如下:
C++ 解法四:
class Solution { public: int trap(vector<int>& height) { stack<int> st; int i = 0, res = 0, n = height.size(); while (i < n) { if (st.empty() || height[i] <= height[st.top()]) { st.push(i++); } else { int t = st.top(); st.pop(); if (st.empty()) continue; res += (min(height[i], height[st.top()]) - height[t]) * (i - st.top() - 1); } } return res; } };
Java 解法四:
class Solution { public int trap(int[] height) { Stack<Integer> s = new Stack<Integer>(); int i = 0, n = height.length, res = 0; while (i < n) { if (s.isEmpty() || height[i] <= height[s.peek()]) { s.push(i++); } else { int t = s.pop(); if (s.isEmpty()) continue; res += (Math.min(height[i], height[s.peek()]) - height[t]) * (i - s.peek() - 1); } } return res; } }
“C++怎么實(shí)現(xiàn)收集雨水”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
文章標(biāo)題:C++怎么實(shí)現(xiàn)收集雨水
當(dāng)前鏈接:http://jinyejixie.com/article36/ppegpg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、靜態(tài)網(wǎng)站、云服務(wù)器、微信公眾號、服務(wù)器托管、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)