基礎算法----算出柱狀體之間能夠存多少水

出題

輸入圖片說明

下午,羣裏面有同窗出了一個簡單的算法題,意思是一個房間內,有多個1立方米的箱子,多個箱子能夠垂直落在一塊兒,問:剩下的空間能夠存多少立方的水(如圖)。算法

本身算法一直很差,可是用進廢退,腦子仍是得多適應如下這種算法的問題。數組

解題

簡單來講,你們作慣了各自字符串,數組,鏈表的題,出題者但願經過一個變種的方式影響如下作題者的思路。 簡單梳理了一下,其實這個題能夠是個數組題,就是將橫座標做爲索引,縱座標箱子的高度做爲數組值,因而能夠簡單的變爲:[0,1,0,4,1,0,1,3 ...]code

根據木桶理論能夠知道,影響盛水多少是由最短的一看板子決定的,因而思路是,求得指定索引區間內,數組中的第一高度和第二高度,這兩個index的步長做爲寬,第二高度做爲高,再減去區間內的全部箱子獲得最終的值:遞歸

寬 * 高 - 佔有的箱子索引

代碼

private static int sum = 0;

    private static List list = new ArrayList();

        list.add(0);
        list.add(1);
        list.add(0);
        list.add(4);
        list.add(1);
        list.add(0);
        list.add(1);
        list.add(3);
        list.add(0);
        list.add(6);
        list.add(0);
        list.add(1);
        list.add(0);
        list.add(3);

        getSum(0, list.size() - 1);
        System.out.println("sum:" + sum);

經過遞歸方式,獲得給定區間內的對高值和第二高值,並求出中間面積圖片

private static void getSum(int start, int end) {
        // 獲取第一高點和第二高點
        int firstIndex = 0;
        int firstH = 0;
        int secondIndex = 0;
        int secondH = 0;

        int h = 0;
        for (int i = start; i <= end; i++) {
            h = Integer.parseInt(list.get(i).toString());
            if (h > firstH) {
                firstH = h;
                firstIndex = i;
            }
        }

        for (int i = start; i <= end; i++) {
            if (i == firstIndex) continue;
            h = Integer.parseInt(list.get(i).toString());
            if (h > secondH) {
                secondH = h;
                secondIndex = i;
            }
        }

        int left = firstIndex >= secondIndex ? secondIndex : firstIndex;
        int right = secondIndex >= firstIndex ? secondIndex : firstIndex;

        if (right - left == 1) return;

        // 獲取所有面積
        h = firstH > secondH ? secondH : firstH;
        int skip = right - left - 1;
        int count = skip * h;

        // 刪除掉佔用的塊
        int remove = removeBlock(left + 1, right);

        sum += count;
        sum -= remove;

        if (left - start > 1)
            getSum(start, left + 1);
        if (end - right > 1)
            getSum(right - 1, end);
    }

刪除區間內的實體箱子ip

private static int removeBlock(int start, int end) {
        int remove = 0;
        for (int i = start; i < end; i++) {
            remove += Integer.parseInt(list.get(i).toString());
        }
        return remove;
    }
相關文章
相關標籤/搜索