https://leetcode.cn/problems/trapping-rain-water/description/
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

这道题如果难的话就是难在思路,怎么去算

三、终版 o(n)
找到最高点,两边依次以最高边为终边,看自己是否有积水,是否有积水取决于历史是否有高过自己的点,积水多少取决于历史最高点-当前高度

image.png

    public int trap(int[] height) {
        if (height.length < 2) {
            return 0;
        }
        int maxIdx = 0;
        for (int i = 1; i < height.length; i++) {
            if (height[i] > height[maxIdx]) {
                maxIdx = i;
            }
        }
        int totalCnt = 0;
        int nearMaxH = height[0];
        for (int i = 1; i < maxIdx; i++) {
            if (height[i] > nearMaxH) {
                nearMaxH = height[i];
            }
            totalCnt += nearMaxH - height[i];
        }
        nearMaxH = height[height.length - 1];
        for (int i = height.length - 2; i > maxIdx; i--) {
            if (height[i] > nearMaxH) {
                nearMaxH = height[i];
            }
            totalCnt += nearMaxH - height[i];
        }
        return totalCnt;
    }

二、排序版 o(nlogn)
先排序->为了找最高点
定位两个最高点a,b;次高点依次去算 与 最近高点a/b 之间 累计的雨量;并更新a/b

    public int trap(int[] height) {
        if (height.length < 2) {
            return 0;
        }
        List<Integer> idxList = IntStream.range(0, height.length).boxed()
            .sorted(Comparator.comparing((Integer idx) -> height[idx]).reversed()).collect(Collectors.toList());
        int left = Math.min(idxList.get(0), idxList.get(1));
        int right = Math.max(idxList.get(0), idxList.get(1));
        int totalCnt = findHeight(left, right, height, height[idxList.get(1)]);
        for (int i = 2; i < idxList.size(); i++) {
            int idx = idxList.get(i);
            if (idx < left) {
                totalCnt += findHeight(idx, left, height, height[idx]);
                left = idx;
            } else if (idx > right) {
                totalCnt += findHeight(right, idx, height, height[idx]);
                right = idx;
            } else {
                // do nothing
            }
            if (left == 0 && right == height.length) {
                break;
            }
        }
        return totalCnt;

    }

    private int findHeight(int left, int right, int[] height, int top) {
        return IntStream.range(left + 1, right).map(idx -> height[idx]).map(h -> top - h).filter(h -> h > 0).sum();
    }

一、枚举版 n^2(未通过时间限制)
按高度、从左到右依次枚举累加,即o(h*n)
小优化:在累加过程中剔除不满足条件的n,然并r,依旧超时不通过

    public int trap(int[] height) {
        int cmpHeight = 1;
        int totalCnt = 0;
        int roundMatchCnt = 0;
        List<Integer> validIdxList = IntStream.range(0, height.length).boxed().collect(Collectors.toList());
        do {
            int lastIdx = -1;
            int cnt = 0;
            roundMatchCnt = 0;
            Iterator<Integer> iter = validIdxList.iterator();
            while (iter.hasNext()) {
                int i = iter.next();
                if (height[i] >= cmpHeight) {
                    if (lastIdx >= 0 && i - lastIdx > 1) {
                        cnt += (i - lastIdx - 1);
                    }
                    lastIdx = i;
                    roundMatchCnt++;
                } else {
                    iter.remove();
                }
            }
            totalCnt += cnt;
            cmpHeight++;
        } while (roundMatchCnt >= 2);
        return totalCnt;
    }

lindsay_bubble
26 声望11 粉丝