https://leetcode.com/articles/surface-area-of-3d-shapes/
On a
N * N
grid, we place some 1 * 1 * 1
cubes.
Each value
v = grid[i][j]
represents a tower of v
cubes placed on top of grid cell (i, j)
.
Return the total surface area of the resulting shapes.
Example 1:
Input: [[2]] Output: 10
Example 2:
Input: [[1,2],[3,4]] Output: 34
Example 3:
Input: [[1,0],[0,2]] Output: 16
Example 4:
Input: [[1,1,1],[1,0,1],[1,1,1]] Output: 32
Example 5:
Input: [[2,2,2],[2,1,2],[2,2,2]] Output: 46
Note:
1 <= N <= 50
0 <= grid[i][j] <= 50
Let's try to count the surface area contributed by
v = grid[i][j]
.
When
v > 0
, the top and bottom surface contributes an area of 2.
Then, for each side (west side, north side, east side, south side) of the column at
grid[i][j]
, the neighboring cell with value nv
means our square contributes max(v - nv, 0)
.
For example, for
grid = [[1, 5]]
, the contribution at grid[0][1]
is 2 + 5 + 5 + 5 + 4. The 2 comes from the top and bottom side, the 5 comes from the north, east, and south side; and the 4 comes from the west side, of which 1 unit is covered by the adjacent column.
Algorithm
For each
v = grid[r][c] > 0
, count ans += 2
, plus ans += max(v - nv, 0)
for each neighboring value nv
adjacent to grid[r][c]
.
public int surfaceArea(int[][] grid) {
int[] dr = new int[] { 0, 1, 0, -1 };
int[] dc = new int[] { 1, 0, -1, 0 };
int N = grid.length;
int ans = 0;
for (int r = 0; r < N; ++r)
for (int c = 0; c < N; ++c)
if (grid[r][c] > 0) {
ans += 2;
for (int k = 0; k < 4; ++k) {
int nr = r + dr[k];
int nc = c + dc[k];
int nv = 0;
if (0 <= nr && nr < N && 0 <= nc && nc < N)
nv = grid[nr][nc];
ans += Math.max(grid[r][c] - nv, 0);
}
}
return ans;
}
For each tower, its surface area is
However, 2 adjacent tower will hide the area of connected part.
The hidden part is
4 * v + 2
However, 2 adjacent tower will hide the area of connected part.
The hidden part is
min(v1, v2)
and we need just minus this area * 2 public int surfaceArea(int[][] grid) {
int res = 0, n = grid.length;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] > 0) res += grid[i][j] * 4 + 2;
if (i > 0) res -= Math.min(grid[i][j], grid[i - 1][j]) * 2;
if (j > 0) res -= Math.min(grid[i][j], grid[i][j - 1]) * 2;
}
}
return res;
}
The bottom and top surface area is 2* the number of cubes.
If the current grid is taller than the grid to the left it means we take the area of this side 2 * height, we *2 because there are two sides - the height of the grid to the left because we already added it.
If the current grid is taller than the grid above it(I guess it depends on which way the axis is facing, but j-1) then we take the area of this side 2 * height, we * 2 because there are two sides sides - the height of the grid with j-1 because we already added it.
If the current grid is taller than the grid to the left it means we take the area of this side 2 * height, we *2 because there are two sides - the height of the grid to the left because we already added it.
If the current grid is taller than the grid above it(I guess it depends on which way the axis is facing, but j-1) then we take the area of this side 2 * height, we * 2 because there are two sides sides - the height of the grid with j-1 because we already added it.