[Why reinvent the wheel??] An easy understood commented solution based on trapping rain 1
```\n/\nBasic physics:\nUnlike bricks, water flows to wherever it could. \ni.e we can't have the follwoing config made with water, but can do it with bricks\n00
```\n/*\nBasic physics:\nUnlike bricks, water flows to wherever it could. \ni.e we can't have the follwoing config made with water, but can do it with bricks\n000\n010\n000\nIn the case above, if the "1" is built with water, that water can't stay. It needs to be spilled!\n\n2 steps Algorithm: \n1. Since we know how to trap rain water in 1d, we can just transfor this 2D problem into 2 1D problems\n    we go row by row, to calculate each spot's water\n    we go column by column, to calculate each spot's water\n\n2. Then, here comes the meat,\n    For every spot that gets wet, from either row or column calculation, the water can possibly spill.\n    We need to check the water height aganist it's 4 neighbors. \n        If the water height is taller than any one of its 4 neightbors, we need to spill the extra water.\n        If we spill any water from any slot, then its 4 neightbors needs to check themselves again.\n            For example, if we spill some water in the current slot b/c its bottm neighbor's height, current slot's top neighbor's height might need to be updated again.\n        we keep checking until there is no water to be spilled.\n*/\n\n\npublic class Solution {\n    public int trapRainWater(int[][] heightMap) {\n        /*FIRST STEP*/\n        if(heightMap.length == 0) return 0;\n        int[][] wetMap = new int[heightMap.length][heightMap[0].length];\n        int sum = 0;\n        /*row by row*/\n        for(int i = 1; i < wetMap.length - 1; i++){\n            wetMap[i] = calculate(heightMap[i]);\n        }\n        /*column by column*/\n        for(int i = 1; i < heightMap[0].length - 1; i++){\n            int[] col = new int[heightMap.length];\n            for(int j = 0; j < heightMap.length; j++){\n                col[j] = heightMap[j][i];\n            }\n            int[] colResult = calculate(col);\n            /*update the wetMap to be the bigger value between row and col, later we can spill, don't worry*/\n            for(int j = 0; j < heightMap.length; j++){\n                wetMap[j][i] = Math.max(colResult[j], wetMap[j][i]);\n                sum += wetMap[j][i];\n            }\n        }\n        /*SECOND STEP*/\n        boolean spillWater = true;\n        int[] rowOffset = {-1,1,0,0};\n        int[] colOffset = {0,0,1,-1};\n        while(spillWater){\n            spillWater = false;\n            for(int i = 1; i < heightMap.length - 1; i++){\n                for(int j = 1; j < heightMap[0].length - 1; j++){\n                    /*If this slot has ever gotten wet, exammine its 4 neightbors*/\n                    if(wetMap[i][j] != 0){\n                        for(int m = 0; m < 4; m++){\n                            int neighborRow = i + rowOffset[m];\n                            int neighborCol = j + colOffset[m];\n                            int currentHeight = wetMap[i][j] + heightMap[i][j];\n                            int neighborHeight = wetMap[neighborRow][neighborCol] + \n                                                              heightMap[neighborRow][neighborCol];\n                            if(currentHeight > neighborHeight){\n                                int spilledWater = currentHeight - Math.max(neighborHeight, heightMap[i][j]);\n                                wetMap[i][j] = Math.max(0, wetMap[i][j] - spilledWater);\n                                sum -= spilledWater;\n                                spillWater = true;\n                            }\n                        }    \n                    }    \n                }\n            }\n        }\n        return sum;\n    }\n    \n    /*Nothing interesting here, the same function for trapping water 1*/\n    private int[] calculate (int[] height){\n        int[] result = new int[height.length];\n        Stack<Integer> s = new Stack<Integer>();\n        int index = 0;\n        while(index < height.length){\n            if(s.isEmpty() || height[index] <= height[s.peek()]){\n                s.push(index++);\n            }else{\n                int bottom = s.pop();\n                if(s.size() != 0){\n                    for(int i = s.peek() + 1; i < index; i++){\n                        result[i] += (Math.min(height[s.peek()], height[index]) - height[bottom]);\n                    }    \n                }\n            }\n        }\n        return result;\n    }   \n    \n}\n````
[]