給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。
上面是由陣列 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度圖,在這種情況下,可以接 6 個單位的雨水(藍色部分表示雨水)。
示例:
輸入: [0,1,0,2,1,0,1,3,2,1,2,1]三指標求解這題讓求柱子中間能盛多少水,首先可以肯定兩邊的兩個柱子是不能盛水的,只有兩邊之間的柱子有可能會盛水。最簡單的一種方式就是使用3個指標,先找到最高的柱子,用乙個指標top指向最高柱子,然後最高柱子左邊用兩個指標,乙個left,乙個right(這裡的left和right指向柱子的高度)。輸出: 6
上面的**如下
int left = height[0]
;//左邊的柱子
int right =0;
//右邊的柱子
int water =0;
//盛水量
for(
int i =
1; i < 最高柱子的下標; i++
)else
}
這裡我們只是計算了左邊的盛水量,我們還需要計算右邊的盛水量,完整**如下
public
inttrap
(int
height)
}//統計最高柱子左邊能接的雨水數量
int left = height[0]
;int right =0;
int water =0;
for(
int i =
1; i < maxindex; i++
)else
}//統計最高柱子右邊能接的雨水數量
right = height[height.length -1]
;for
(int i = height.length -
2; i > maxindex; i--
)else
}//返回盛水量
return water;
}
雙指標求解這裡我們還可以使用雙指標,乙個指向最左邊,乙個指向最右邊,如下圖所示。
這裡要明白一點,最開始的時候如果左邊柱子從左往右是遞增的,那麼這些柱子是不能盛水的,比如像下面這樣
同理最開始的時候如果右邊的柱子從右往左是遞增的,也是不能盛水的。所以上面圖中right指向的是右邊第2根柱子。確定左右兩邊柱子的的**如下
int left =
0, right = height.length -1;
while
(left < right && height[left]
<= height[left +1]
) left++
;while
(left < right && height[right]
<= height[right -1]
) right--
;
通過上面的計算,確定left和right的值之後,在left和right之間相當於構成了乙個桶,桶的高度是最矮的那根柱子。然後我們從兩邊往中間逐個查詢,如果查詢的柱子高度小於桶的高度,那麼盛水量就是桶的高度減去我們查詢的柱子高度,如果查詢的柱子大於桶的高度,我們要更新桶的高度。我們來看下最終**
public
inttrap
(int
height)
}else}}
return water;
}
上面有3個while迴圈,看的有點眼花繚亂,實際上我們還可以把它合併為乙個,**如下
public
inttrap
(int
height)
else
}return water;
}
雙指標**簡化實際上我們還可以再進一步簡化,我們看下下面這個圖。此時left和right圍成的桶的高度是4,這個時候如果right往左移,那麼移動之後這個值是小於4的,也就是小於桶的高度,所以這個時候桶的高度是不變的。假如right往左移之後的值是大於4,比如5,那麼桶的高度是要更新的。
我們只要確定桶的高度之後,那麼盛水量就好求了。
public
inttrap
(int
height)
return water;
}
總結接雨水我們把它想象成兩邊的兩根柱子圍成乙個桶,桶的高度就是最矮的那根柱子,只要確定了桶的高度,我們遍歷中間柱子的時候就可以確定盛水量了。如果柱子的高度大於桶的高度,很明顯是不能盛水的,只有柱子的高度小於桶的高度的時候才會盛水。這裡有一點要注意的是當柱子的高度大於桶的高度的時候我們要更新桶的高度,當柱子的高度小於桶時候,桶的高度是不變的。這題使用雙指標很巧妙的解決了上面的問題。
接雨水問題 雙指標
暴力法 def rain lis n len lis l max 0 for in range n 記錄每個點為中心,左邊和右邊最高的板高度 r max 0 for in range n for i in range 1,n l max i max l max i 1 lis i 1 for j i...
42 接雨水 雙指標
對於乙個較低的坑來說,其儲水量高度取決於左側最高柱與右側最高柱的較小高度 可以用兩個指標,分別從左右兩邊往中間逼近,左側或者右側的儲水量只取決於當前一側的高度差 if len height 0 return 0left,right 0,len height 1 left max,right max ...
LeetCode 42 接雨水 雙指標
主要方法 雙指標 正反遍歷 解釋說明 1.正向遍歷 先確定池子左牆初始化為第乙個bar,從第 2 個 bar 開始遍歷右牆,同時記錄中間的 bar 高度和,當右牆大於等於左牆的時候就有第一灘積水了,左右牆距離 左牆高度 中間 bar 和 就是這灘積水的體積,同時將右牆認定為下乙個左牆,同時重新記錄b...