11. Container with most water
Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.算法
Note: You may not slant the container and n is at least 2.函數
Example:
Input: [1,8,6,2,5,4,8,3,7]
Output: 49code
網上給出的最優算法都比較相似,其基本想法是:將挑選的兩條邊分別從兩端$a_0, a_n$開始向中間移動,每一次只能移動兩條邊中的一條。每次移動的標準是將較小的那條邊往中間移動一格。若是移動後的面積有所增加,則將面積最大值更新。當兩條邊相遇時,則中止。orm
網上幾乎都只有這個算法的描述,而沒有提供一個嚴格的數學證實。和好友Meiyf討論後,整理出這個算法的數學證實。ip
考慮分佈在左右兩邊的移動指標$a_l, a_r$,它們分別從兩端$a_0, a_n$開始,經過$a_l$右移、$a_r$左移的方式,來搜索最優解。leetcode
假設最優解爲$a_i, a_j$,則咱們有:$0 \leq i < j \leq n$。根據算法的移動方式,老是能夠經過「$a_l$從$a_0$右移、$a_r$從$a_n$左移」若干步的方式,到達$a_i, a_j$。get
因爲算法每一次只能移動一步(即$a_l$右移一步或$a_r$左移一步),因此兩種狀況:數學
必然有一種先發生。不妨假設$a_l$先到達$a_i$(那麼此時,$a_r$也就還未經過左移到達$a_j$,它還在$a_j$的右側)。那麼,咱們只需證實:it
在現有的算法下,後續的更新步驟 都只能是:$a_r$不斷左移、直到到達$a_j$。
咱們能夠經過反證法來證實上述結論。io
令函數$h(a_t)$表示點$a_t$對應的線段長度,令$w(a_s, a_t)$表示點$a_s$和$a_t$構成的線段長度。
若假設不成立,則存在某一步:在$a_r$還未經過左移到達$a_j$時,停留在$a_i$的$a_l$須要右移一步。
下面咱們來證實不可能出現上面這種狀況。
若上述發生,則咱們有如下結論:
由此,咱們能夠獲得由$a_i, a_r$兩條邊造成的面積爲:$$S^* = h(a_i) * w(a_i, a_r).$$
這裏的高度之因此取爲$h(a_i)$,是由於上面第2條已經說明了$h(a_i)$比$h(a_r)$小。
而此時,由於第1條已經說明$j < r$,因此$w(a_i, a_r) > w(a_i, a_j)$。因此咱們有:
$$S^* = h(a_i) * w(a_i, a_r) > h(a_i) * w(a_i, a_j) \geq \min{\{h(a_i), h(a_j)\}} * w(a_i, a_j) = S_{max}$$
矛盾。因此假設命題不成立,進而當$a_l$到達$a_i$後,後續的全部更新步驟都只能是$a_r$不斷左移、直到到達$a_j$。
因此,在這樣的算法之下,必定可以到找到面積的最優解$S_{max}$。