You are given an n x n grid where you have placed some 1 x 1 x 1 cubes. Each value v = grid[i][j] represents a tower of v cubes placed on top of cell (i, j).
After placing these cubes, you have decided to glue any directly adjacent cubes to each other, forming several irregular 3D shapes.
Return the total surface area of the resulting shapes.
Note: The bottom face of each shape counts toward its surface area.
Example 1:
Input: grid = [[1,2],[3,4]] Output: 34
Example 2:
Input: grid = [[1,1,1],[1,0,1],[1,1,1]] Output: 32
Example 3:
Input: grid = [[2,2,2],[2,1,2],[2,2,2]] Output: 46
Constraints:
n == grid.length == grid[i].length1 <= n <= 500 <= grid[i][j] <= 50When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
Imagine each cube in the 3D shape is separate. The brute force strategy calculates the surface area of each cube individually and then subtracts the overlapping faces where cubes are touching.
Here's how the algorithm would work step-by-step:
def surface_area_3d_brute_force(grid):
total_surface_area = 0
number_rows = len(grid)
number_columns = len(grid[0]) if number_rows > 0 else 0
for row in range(number_rows):
for column in range(number_columns):
cube_height = grid[row][column]
if cube_height > 0:
# Each cube initially contributes 6 faces to the total surface area
total_surface_area += 6 * cube_height
# Subtract overlapping faces with neighboring cubes
# Check for overlap with the cube above
if row > 0:
neighbor_height = grid[row - 1][column]
total_surface_area -= 2 * min(cube_height, neighbor_height)
# Check for overlap with the cube to the left
if column > 0:
neighbor_height = grid[row][column - 1]
total_surface_area -= 2 * min(cube_height, neighbor_height)
return total_surface_areaThe key to efficiently calculating the surface area of a 3D shape built from cubes is to avoid double-counting areas where cubes touch. Instead of calculating the surface area of each cube individually, we account for how much area is blocked by adjacent cubes.
Here's how the algorithm would work step-by-step:
def surfaceArea(grid):
grid_length = len(grid)
grid_width = len(grid[0])
total_surface_area = 0
for row_index in range(grid_length):
for column_index in range(grid_width):
if grid[row_index][column_index] > 0:
# Start by assuming each cube contributes its full surface area.
total_surface_area += 6 * grid[row_index][column_index]
# Now, subtract the areas of the touching faces.
# Check for neighbors to the left.
if row_index > 0:
total_surface_area -= 2 * min(grid[row_index][column_index], grid[row_index - 1][column_index])
# Check for neighbors below.
if column_index > 0:
total_surface_area -= 2 * min(grid[row_index][column_index], grid[row_index][column_index - 1])
return total_surface_area| Case | How to Handle |
|---|---|
| Null or empty grid input | Return 0 immediately as there's no shape to calculate surface area for. |
| Grid with zero dimensions (e.g., grid[0].length == 0) | Return 0 since there is nothing to compute surface area on. |
| Grid with very large dimensions potentially leading to integer overflow in surface area calculation | Use a long data type to store the surface area to prevent integer overflow. |
| Cells with extremely large values potentially leading to integer overflow in surface area calculation | Use long to store height values from grid to prevent overflow during computation. |
| All cells have a value of 0 | Return 0 as no cubes exist. |
| Grid contains only one cube (all other cells are 0) | The surface area will be 6 minus the shared faces which will be properly calculated. |
| Two adjacent cells have very different heights, maximizing exposed surface area | The surface area difference will be correctly calculated due to the absolute difference in heights. |
| Grid is a single row or single column | The algorithm handles this case correctly by calculating the exposed faces within the single row or column. |