LeetCode 11 的數學證實 | Container With Most Water

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_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$須要右移一步。

下面咱們來證實不可能出現上面這種狀況。

若上述發生,則咱們有如下結論:

  1. $l = i < j < r$
  2. $h(a_i) = h(a_l) < h(a_r)$。由於根據算法,只有長度更小的那一條邊才能向中間移動。因此,只有當$h(a_l)$小於$h(a_r)$時,纔可能出現$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}$。

相關文章
相關標籤/搜索