基础算法----算出柱状体之间能够存多少水

出题

输入图片说明

下午,群里面有同窗出了一个简单的算法题,意思是一个房间内,有多个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;
    }
相关文章
相关标签/搜索