算法 蓄水問題

問題:    
  給定一個數組,想象成一個桶。問最多能裝多少水?

例【1,5,3,6】 最多裝2格水 O O ~ O O ~ O O O O O O O O O O O


解題思路:
  咱們把每一列當成一塊板,根據分析,第一塊板和最後一塊板必定不能蓄水,因此問題變成了全部板所能蓄水最大值的總和。先明確這個思路,以後再想辦法。

那麼如何肯定當前板能夠蓄多少水呢?和它左右兩邊最長的板有關係。等於左右兩邊最長板的較小者減去當前板的長度和0取最大值。
表示爲:
    當前板蓄水量 = math.max(0, math.min(左最長板,右最長板) - 當前)
    第1、最後一塊板蓄水量 = 0

方法一:O(n^2)
  簡單暴力,挨個遍歷每一塊板,求出左右最大值,根據上面公式進行計算。不作演示

方法二:O(n)
  根據方法一可知,時間複雜度主要在尋找每一塊板的左右最大值。那麼優化的方向就是使用O(n)複雜度得到每一塊板的左右最大值。
怎麼作呢?藉助輔助數組。
例如【1,5,3,6】,則左邊最大值數組爲【1,5,5,6】,右邊最大值數組爲【6,6,6,6】
三個數組分別表示當前板長度,當前板的左邊板最大長度、當前板的右邊板最大長度。

    public static int shui(int[] param) {
        if(param == null || param.length < 2) return 0;
        
        int[] L = new int[param.length];
        int[] R = new int[param.length];
    
        for(int i=1;i<param.length;i++) {
            L[i] = Math.max(param[i], param[i - 1]);
        }
        for(int i=param.length - 2;i>0;i--) {
            R[i] = Math.max(param[i], param[i + 1]);
        }
        
        int shui = 0;
        for(int i = 1; i<param.length-1;i++)
        {
            shui += Math.max(0, Math.min(L[i], R[i]) - param[i]);
        }
        return shui;
    }
方法三:O(n)
  方法二空間複雜度太大,因此還有優化空間。
能夠從兩邊同時進行判斷,而且保存當前左右最大值。
若是左邊最大值小於右邊最大值,那麼左邊的當前板所能蓄水量就可肯定 = math.max(0, 左最大值 - 當前)而且當前索引++,標記左邊最大值 = math.max(左最大值,當前板)。
若是右邊最大值小於左邊最大值,那麼右邊的當前板所能蓄水量就可肯定 =
math.max(0, 右最大值 - 當前)而且當前索引--,標記右邊最大值 = math.max(右最大值,當前板)。
若是相等,隨便歸屬一邊,或兩邊一塊兒計算。

    /*
     * 給定一個數組,想象成一個桶。問最多能裝多少水
     * 例【1,5,3,6】   最多裝2格水
     *          O
     *    O  ~  O
     *    O  ~  O
     *    O  O  O 
     *    O  O  O
     * O  O  O  O
     * 
     */
    
    public static int shui(int[] param) {
        if(param == null || param.length < 2) return 0;
        
        int L = 1, R = param.length-2, shui = 0;
        int lmax = param[0], rmax = param[R + 1];
        while(L<=R) {
            if(lmax <= rmax) {
                shui += Math.max(0, lmax - param[L]);
                lmax = Math.max(lmax, param[L++]);
            }else {
                shui += Math.max(0, rmax - param[R]);
                rmax = Math.max(rmax, param[R--]);
            }
        }
        return shui;
    }
    
    public static void main(String[] args) {
        int[] a = {2,1,3,5,2,6};
        System.out.println(shui(a));
    }
相關文章
相關標籤/搜索