755. Pour Water

We are given an elevation map, heights[i] representing the height of the terrain at that index. The width at each index is 1. After V units of water fall at index K, how much water is at each index?
这道题很有意思,
思路是simulate。
先看水会不会往左流,如果水往左流,则左边一定是会比右边低才能流。如果左右高度相等,那可以试探一下再往左有没有更低的,如果左边可以找到更低的,则水就移过来,找不到的话,水就不再往左走了。就是往左找一个递减序列,停在第一个出现的最低值上。如果左边找到的这个最低值不比k点低,则看一下右边会不会流到更低的地方去。如果都找不到,水滴就留在这里。
下面贴下代码;

    public int[] pourWater(int[] heights, int V, int K) {
        while (V-- > 0) {
            int l = findBest(heights, K, -1);
            if (heights[l] < heights[K]){
                heights[l]++;
                continue;
            }
            int r = findBest(heights, K, 1);
            if (heights[r] < heights[K]) {
                heights[r]++;
                continue;
            }
            heights[K]++;
        }
        return heights;
    }
    private int findBest(int[] heights, int start, int offset) {
        int lowestLocation = start;
        int cur = start;
        while (cur + offset >= 0 && cur + offset < heights.length &&
              heights[cur + offset] <= heights[cur]) {
            cur += offset;
            if (heights[cur] < heights[lowestLocation]) {
                lowestLocation = cur;
            }
        }
        return lowestLocation;
    }

一个follow up是如果左右两边没有无限高的墙怎么办
答案就是看下左边会不会流下去,右边会不会流下去。如果有一边会流下去, 就停止更新了。怎么判断会不会流下去 ? 就是在水试探性的往前走的时候看它会不会走到最外面一格。
或者在左右再加一列为负无穷,然后每次reset为负无穷。

    public int[] pourWaterFollowUp(int[] heights, int V, int K) {
        // follow up : do not assume there infinite walls on two sides
        while (V-- > 0) {
            int l = findBest2(heights, K, -1); 
            int r = findBest2(heights, K, 1); 
            if (l < 0 || r >= heights.length) {
                continue;
            } else if (heights[l] < heights[K]){
                heights[l]++;
            } else if (heights[r] < heights[K]) {
                heights[r]++;
            } else {
                heights[K]++;
            }
        }
        return heights;
    }
    private int findBest2(int[] heights, int start, int offset) {
        int lowestLocation = start;
        int cur = start;
        while (cur + offset >= 0 && cur + offset < heights.length &&
                heights[cur + offset] <= heights[cur]) {
            cur += offset;
            if (heights[cur] < heights[lowestLocation]) {
                lowestLocation = cur;
            }
        }
        if (cur == 0 || cur == heights.length - 1) return cur + offset;
        return lowestLocation;
    }

对于这个follow up一种更简单的解法是 左右再加一列为负无穷,然后每次reset为负无穷, 这样就特别特别好改了

    public int[] pourWaterFollowUp2(int[] heights, int V, int K) {
        int[] helperHeights = new int[heights.length + 2];
        for (int i = 1; i <= heights.length; i++) {
            helperHeights[i] = heights[i - 1];
        }
        helperHeights[0] = Integer.MIN_VALUE;
        helperHeights[heights.length + 1] = Integer.MIN_VALUE;
        while (V-- > 0) {
            helperHeights[0] = Integer.MIN_VALUE;
            helperHeights[heights.length + 1] = Integer.MIN_VALUE;
            int l = findBest(helperHeights, K, -1);
            if (helperHeights[l] < helperHeights[K]){
                heights[l]++;
                continue;
            }
            int r = findBest(helperHeights, K, 1);
            if (helperHeights[r] < helperHeights[K]) {
                helperHeights[r]++;
                continue;
            }
            helperHeights[K]++;
        }
        return Arrays.copyOfRange(helperHeights, 1, helperHeights.length - 1);
    }

下面的代码带打印功能

class Solution {
    public int[] pourWater(int[] heights, int V, int K) {
        int N = heights.length;
        int[] ans = new int[N];
        for (int i = 0; i < N; i++) ans[i] = heights[i];
        printShape(heights, ans);
        while (V-- > 0) {
            int leftPos = findLower(ans, K, -1);
            int rightPos = findLower(ans, K, 1);
            if (leftPos != K) {
                ans[leftPos]++;
            } else if (rightPos != K) {
                ans[rightPos]++;
            } else ans[K]++;
            printShape(heights, ans);
        }
        return ans;
    }
    private int findLower(int[] ans, int start, int offset) {
        int lowestLocation = start;
        int curLocation = start;
        while (curLocation + offset >= 0 && curLocation + offset < ans.length) {
            if (ans[curLocation + offset] <= ans[curLocation]) {
                curLocation += offset;
                if (ans[curLocation] < ans[lowestLocation]) {
                    lowestLocation = curLocation;
                }
            } else break;
        }
        return lowestLocation;
    }
    private void printShape(int[] shape, int[] filledShape) {
        int max = shape[0];
        for (int n : filledShape) max = Math.max(n, max);
        for (int h = max + 2; h >= 0; h--) {
            StringBuilder sb = new StringBuilder();
            for (int i = -1; i <= shape.length; i++) {
                if (i == -1 || i == shape.length) {
                    sb.append("#");
                } else {
                    if (h <= shape[i]) {
                        sb.append("#");
                    } else if (h <= filledShape[i]){
                        sb.append("w");
                    } else {
                        sb.append(" ");
                    }
                }
            }
            System.out.println(sb.toString());
        }
        System.out.println(Arrays.toString(filledShape));
    }
}

你可能感兴趣的:(755. Pour Water)