摘要:一題目接雨水給定個非負(fù)整數(shù)表示每個寬度為的柱子的高度圖,計算按此排列的柱子,下雨之后能接多少雨水。上面是由數(shù)組表示的高度圖,在這種情況下,可以接個單位的雨水藍(lán)色部分表示雨水。提交,答案錯誤。出錯的測試用例為。
做有意思的題是要付出代價的,代價就是死活做不出來。一、題目
接雨水:
給定 n 個非負(fù)整數(shù)表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之后能接多少雨水。二、我的答案 思路1
上面是由數(shù)組 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍(lán)色部分表示雨水)。
示例 1:
輸入: [0,1,0,2,1,0,1,3,2,1,2,1]
輸出: 6
???????前段時間有在看一個俄羅斯方塊的代碼,所以第一個思路是從下到上一層一層計算,先把數(shù)組中所有的數(shù)-1,然后去掉數(shù)組兩端的-1,再統(tǒng)計數(shù)組中-1的個數(shù),即為本層接的雨水。這種暴力解法應(yīng)該是可行的,我并沒有把思路落到紙上,各位感興趣可以試一下。
思路2???????接雨水嘛,兩邊比中間高就能接到,那么我只需要求出所有比左右兩邊高的點,他們兩兩組合就成一個可以接到水的坑,以原題中的示例1為例,下標(biāo)為1,3,7,10的點就是我們所求。代碼如下
/** * @param {number[]} height * @return {number} */ var trap = function(height) { function fillister (arr) { let result = 0 let baseLine = arr[0] <= arr[arr.length - 1] ? arr[0] : arr[arr.length - 1] let difference for(let i = 0; i < arr.length; i++) { difference = baseLine - arr[i] difference > 0 ? result += difference : null } return result } let result = 0 let bigger, smaller, the_dot for(let begin = 0; begin < height.length; begin++) { bigger = (height[begin - 1] || 0) < height[begin] smaller = (height[begin + 1] || 0) < height[begin] if (smaller && bigger) { if (the_dot !== undefined) { result += fillister(height.slice(the_dot, begin + 1)) } the_dot = begin } } return result };
???????遍歷參數(shù)數(shù)組height,只要符合條件,且不是第一個符合條件的點,就計算該點與之前點之間的積水。提交,答案錯誤。出錯的測試用例為[5,1,2,1,5]。
???????原來按照上述思路,只計算了[5,1,2]和[2,1,5]兩個小水洼,但是[5,1,2,1,5]本身就是個大水洼。意識到計算目標(biāo)點的函數(shù)需要遞歸。
???????根據(jù)這個想法,我進行了大量的編碼,因為這個遞歸調(diào)用的邊界情況比較麻煩,而且越寫越懷疑自己的思路,我始終覺得優(yōu)秀的題解應(yīng)該是簡單的。這里只放出其中對我產(chǎn)生啟發(fā)的一個片段。
function noNeedToCall (arr) { let max = Math.max.apply(null, arr) let maxIndex = arr.indexOf(max) for(let i = 0, len = arr.length - 1; i < len; i++){ if(i < maxIndex) { if(arr[i] > arr[i + 1]) return false } else { if(arr[i] < arr[i + 1]) return false } } return true }
???????上面這段代碼的作用在于遞歸函數(shù)調(diào)用的最后,判斷是否需要繼續(xù)遞歸。如果在最大值左邊的數(shù)組是遞增或持平,在最大值右邊的數(shù)組是遞減或持平的就不需要遞歸,否則繼續(xù)調(diào)用。也就是說最后求出來是以最大值為界,左邊一個水洼,右邊一個水洼(杠精:“[2,1,3,1,4,1,2]這個例子中最大值4左邊有兩個水洼,垃圾博主”,)左邊一個水洼集,右邊一個水洼集。
???????雖然左右兩個水洼,但是決定他們范圍的兩個點中的最大值都肯定都是整個數(shù)組的最大值,也就是說決定他們積水量的值也就是較小值是存在于左右兩邊的,那我為什么要各種調(diào)用各種遞歸,直接分左右兩側(cè)共循環(huán)一遍數(shù)組就好了。上代碼
/** * @param {number[]} height * @return {number} */ var trap = function(height) { const max = Math.max.apply(null, height) const maxIndex = height.indexOf(max) let i = 0, temp = 0, result = 0 for (i = 0; i < maxIndex; i++) { if (height[i] >= temp) { temp = height[i] } else { result += temp - height[i] } } temp = 0 for (i = height.length - 1; i > maxIndex; i--) { if (height[i] >= temp) { temp = height[i] } else { result += temp - height[i] } } return result };三、優(yōu)秀答案
/** * @param {number[]} height * @return {number} */ var trap = function(height) { if (!height || !height.length) { return 0; } let maxLeftWall = 0; let maxRightWall = 0; let water = 0; let i = 0; let j = height.length - 1; while (i < j) { if (height[i] < height[j]) { if (height[i] >= maxLeftWall) { maxLeftWall = height[i]; } else { water += maxLeftWall - height[i]; } i++; } else { if (height[j] >= maxRightWall) { maxRightWall = height[j]; } else { water += maxRightWall - height[j]; } j--; } } return water; };
???????思路是相似的,不過對于處理最大值的方式不同,代碼放這兒就不細(xì)說了
四、路漫漫其修遠(yuǎn)兮???????這道題真的難了我好久,從想到求水洼兩端的點,到遞歸調(diào)用的處理,到推翻之前的思路左右分別處理。過程中各種測試用例a通過測試用例b不通過,跟著debugger一點點看然后改然后測試用例b通過測試用例a又不通過。
???????最后思路迸發(fā)出來寫出來提交通過,這種感覺真是爽快,就像是穿著新內(nèi)褲迎接新年來到的早晨一樣。
???????你不要過來?。。?!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/104649.html
摘要:復(fù)雜度思路因為蓄水多少取決于比較短的那塊板的長度。代碼復(fù)雜度思路考慮說明時候需要計算蓄水量當(dāng)?shù)臅r候,需要計算能儲存的水的多少。每次還需要取出一個作為中間值。如果則一直向里面壓進去值,不需要直接計算。 Leetcode[42] Trapping Rain Water Given n non-negative integers representing an elevation map ...
摘要:我先通過堆棧的方法,找到一個封閉區(qū)間,該區(qū)間可以盛水,該區(qū)間的右節(jié)點可以作為下一個封閉區(qū)間的起點。思路三堆棧的聰明使用在這里,堆棧允許我們漸進的通過橫向分割而非之前傳統(tǒng)的縱向分割的方式來累加計算盛水量。 題目要求 Given n non-negative integers representing an elevation map where the width of each bar...
摘要:一種是利用去找同一層的兩個邊,不斷累加寄存。雙指針法的思想先找到左右兩邊的第一個峰值作為參照位,然后分別向后向前每一步增加該位與參照位在這一位的差值,加入,直到下一個峰值,再更新為新的參照位。 Problem Given n non-negative integers representing an elevation map where the width of each bar i...
摘要:從右向左遍歷時,記錄下上次右邊的峰值,如果左邊一直沒有比這個峰值高的,就加上這些差值。難點在于,當(dāng)兩個指針遍歷到相鄰的峰時,我們要選取較小的那個峰值來計算差值。所以,我們在遍歷左指針或者右指針之前,要先判斷左右兩個峰值的大小。 Trapping Rain Water Given n non-negative integers representing an elevation map ...
407. Trapping Rain Water II 題目鏈接:https://leetcode.com/problems... 參考discussion里的解法:https://discuss.leetcode.com/... 參考博客里的解釋:http://www.cnblogs.com/grandy... public class Solution { public int tra...
閱讀 2580·2021-09-06 15:02
閱讀 3213·2021-09-02 10:18
閱讀 2835·2019-08-30 15:44
閱讀 695·2019-08-30 15:43
閱讀 1959·2019-08-30 14:08
閱讀 2767·2019-08-30 13:16
閱讀 1408·2019-08-26 13:52
閱讀 939·2019-08-26 12:21