leetcode11. Container With Most Water 盛水最多的容器

題目要求:給一個數組,其中數組在下標i處的值爲A[i],座標(i,A[i])和座標(i,0)構成一條垂直於座標軸x的直線。現任取兩條垂線和x軸組成四邊形容器。問其中盛水量最大爲多少?面試

思路一:暴力的雙重循環

這種實現很是原始,在這裏就不贅述了,時間複雜度爲O(n2),在數據量較大的時候,性能不好算法

思路二:雙指針

減小循環的核心思路是省去沒有必要的遍歷,而且確保所需的答案必定能被遍歷到
假設如今有一個容器,則容器的盛水量取決於容器的底和容器較短的那條高
則咱們能夠從最大的底長入手,即當容器的底等於數組的長度時,則容器的盛水量爲較短邊的長乘底
可見 只有較短邊會對盛水量形成影響,所以移動較短邊的指針,並比較當前盛水量和當前最大盛水量。直至左右指針相遇。數組

主要的困惑在於如何移動雙指針才能保證最大的盛水量被遍歷到
假設有左指針left和右指針right,且left指向的值小於right的值,假如咱們將右指針左移,則右指針左移後的值和左指針指向的值相比有三種狀況微信

  1. 右指針指向的值大於左指針
    這種狀況下,容器的高取決於左指針,可是底變短了,因此容器盛水量必定變小
  2. 右指針指向的值等於左指針
    這種狀況下,容器的高取決於左指針,可是底變短了,因此容器盛水量必定變小
  3. 右指針指向的值小於左指針
    這種狀況下,容器的高取決於右指針,可是右指針小於左指針,且底也變短了,因此容量盛水量必定變小了

綜上所述,容器高度較大的一側的移動只會形成容器盛水量減少
因此應當移動高度較小一側的指針,並繼續遍歷,直至兩指針相遇。性能

public int maxArea(int[] height) {
        int left = 0;
        int right = height.length-1;
        int max = 0;
        while(left<right){
            max = Math.max(max, Math.min(height[left], height[right])*(right-left));
            if(height[left]<height[right]){
                left++;
            }else{
                right--;
            }
        }
        return max;
    }

更新:更嚴謹的證實

以前證實的只是在左指針不改變的狀況下,左移右指針只會形成容器的容量減少。可是一旦緊接着左指針發生變化,就沒法證實以該左指針爲一側高,右指針右側的值生成的容器的容量比當前值小。
如下補充一個簡單的反證法證實算法的合理性
當前的算法爲:使用兩個指針分別指向數組的頭和尾。指向的值較小的那個指針移動,即左指針右移,右指針左移。當左右指針相遇時,指針
假設:該算法並無遍歷到容量最大的狀況
咱們令容量最大時的指針爲p_left和p_right。根據題設,咱們能夠假設遍歷時左指針先到達p_left,可是當左指針爲p_left時,右指針尚未通過p_right左指針就移動了
已知當左指針停留在p_left時,它只有在兩種場景下會發生改變spa

  1. 左指針和右指針在p_left相遇,則右指針必定在前往p_left的途中通過p_right,與題設矛盾
  2. 右指針位於p_right右側且當前的值大於左指針。則在這種狀況下,此時容器的盛水量比題設中最大的盛水量還要大,與題設矛盾

所以該算法的遍歷必定通過了最大的盛水量的狀況指針

clipboard.png
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~code

相關文章
相關標籤/搜索