Problem 892

Abstract / Summary

Calculate the total exposed area of a 3D shape made of stacked cubes by checking each cube's visible faces.

Note

The full problem description, including helpful examples, can be found on LeetCode.

Python 0892.py

class Solution:
    def surfaceArea(self, grid: List[List[int]]) -> int:
        width  = len(grid[0])
        height = len(grid)

        def get(x, y):
            if 0 <= x < width and 0 <= y < height:
                return grid[y][x]
            return 0

        result = 0
        for y in range(height):
            for x in range(width):
                if get(x, y) == 0:
                    continue

                result += 2 # top and bottom
                # four sides, only if taller than neighbors
                result += max(0, get(x, y) - get(x - 1, y))
                result += max(0, get(x, y) - get(x + 1, y))
                result += max(0, get(x, y) - get(x, y - 1))
                result += max(0, get(x, y) - get(x, y + 1))

        return result
24 lines | 804 bytes | submitted November 30, 2023 | GitHub   10% comment ratio | tab size 4 | low complexity

Difficulty

This problem is ranked as
easy medium hard

and has an acceptance rate of about 71% (80k+ submissions).

Typical patterns to solve this problem:
  • Array
  • Geometry
  • Math
  • Matrix
I solved 663 easy, 1250 medium and 309 hard problems

AI Disclaimer

Every single line of code was written by me, 100% from scratch, between August 2023 and August 2024.
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.

See this dedicated page for more details.
LeetCode profile | GitHub repo

Code Walkthrough

Overview

The provided implementation computes the total surface area of a 3-dimensional shape that is built from stacked unit cubes on a rectangular grid. Each cell of the input matrix contains a non-negative integer representing the height of the stack at that position. The algorithm iterates over every cell, adds the contribution of the top and bottom faces when the height is non-zero, and then adds the contribution of the four lateral faces that are exposed because the current stack is taller than its neighboring stacks. Boundary cells are treated uniformly by a helper that returns zero for out-of-range coordinates, which effectively models an empty neighbor outside the grid.

Key Steps

Determining Grid Dimensions

The first two statements extract the horizontal and vertical extents of the matrix. These values are used throughout the algorithm to bound coordinate checks.

width  = len(grid[0])
height = len(grid)

Safe Neighbor Access

A nested helper function get abstracts the retrieval of a cell’s height. It returns the actual height when the coordinates lie inside the grid and returns zero otherwise. This design eliminates the need for explicit boundary checks at each neighbor comparison and naturally handles the case where a stack lies on the outer edge of the grid.

def get(x, y):
    if 0 <= x < width and 0 <= y < height:
        return grid[y][x]
    return 0

Iterating Over All Cells

Two nested loops walk through every row and column index. The inner body is executed only when the current cell contains at least one cube; cells with height zero are skipped early, which avoids unnecessary calculations for empty positions.

for y in range(height):
    for x in range(width):
        if get(x, y) == 0:
            continue
        # further processing follows

Adding Top and Bottom Faces

When a stack is present, the algorithm immediately adds two units to the result, accounting for the topmost and bottommost faces of the column. This contribution is constant for any non-zero height.

result += 2  # top and bottom

Computing Exposed Lateral Faces

For each of the four directions-left, right, front, and back-the code calculates the height difference between the current stack and its neighbor. The max(0, …) construct ensures that only positive differences contribute, which corresponds to the portion of the side that is not covered by the adjacent column. If the neighbor is taller or equal, the contribution is zero, correctly handling cases where a side is completely hidden.

result += max(0, get(x, y) - get(x - 1, y))
result += max(0, get(x, y) - get(x + 1, y))
result += max(0, get(x, y) - get(x, y - 1))
result += max(0, get(x, y) - get(x, y + 1))

Returning the Accumulated Surface Area

After all cells have been processed, the accumulated total is returned as the final surface area.

return result

Edge Cases Handled

The algorithm gracefully manages cells that lie on the perimeter of the grid. Because the get helper returns zero for coordinates outside the valid range, a stack on the edge contributes its full side height to the surface area, as if it were adjacent to empty space. Cells with a height of zero are ignored entirely, preventing any addition of faces for empty positions. When neighboring stacks have equal height, the lateral contribution becomes zero, correctly modeling a seamless interface without any exposed area. The use of max(0, …) also protects against negative differences, ensuring that only exposed portions are counted.

Performance Optimizations

The design consolidates boundary handling into a single helper function, which reduces repetitive conditional logic inside the main loops. By skipping zero-height cells early, the algorithm avoids unnecessary neighbor checks for empty locations, saving work proportional to the number of empty cells. The use of arithmetic expressions (max(0, …)) to compute side contributions eliminates the need for explicit if statements for each direction, resulting in a tight inner loop that executes a constant amount of work per visited cell. The overall structure processes the grid in a single pass, keeping the runtime proportional to the total number of cells.

written by openai gpt

ELI5 - Simplified Explanation

Imagine a city made entirely of toy blocks sitting on a flat table. The grid is like a map that tells how many blocks are stacked in each tiny square spot on the table. Some spots have no blocks, some have one, and some might be tall towers.

To figure out how much paint is needed to cover all the outside parts of these towers, the code looks at every single spot on the map one by one. For every spot that has blocks, there is automatically a shiny top cover and a base hidden on the table, so it adds two to the total.

Then, it checks the four sides of each stack to see if they are touching any neighbor stacks. If a neighbor is shorter or empty, the exposed part of the tall tower needs paint. It does this by comparing the height of the current tower to the heights of the neighbors sitting to the left, right, above, and below. If the current tower is taller, the extra height counts as a side that needs paint. The code keeps track of all these little squares of color as it moves across the whole city map until every single visible surface has been counted.

written by google gemini

Code Quality

Several LLMs ranked my code quality on a scale from 1 (very poor) to 10 (outstanding):
n = 26 | median = 8 | μ = 8.08 | σ = 0.67

Complexity Analysis

Time: polynomial
As a rule of thumb, the maximum input size for one second execution time is
  • factorial: up to 10 elements
  • exponential: up to 20 elements
  • polynomial: a few thousand elements
  • loglinear: up to 100,000 elements
  • linear: a few million elements
  • logarithmic: a billion elements
  • constant: practically unlimited
generated automatically

Other Solutions

I wrote a basic crawler to find other solutions to that problem.
Obviously, I did that after I solved the problem myself.

In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.

And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.

(click on a column header to sort the table)
author
author solutions
www AlgoMonster C++ Python Java TS
WalkCCC C++ Python Java
leetcode.ca C++ Python Java Go
LeetcodeHelp C++ Python Java
Progiez C++ Python Java
github BigEggStudy C#
black-shadows C++
charles-wangkai Java
everthis JS
halfrost Go
JoshCrozier JS
keineahnung2345 C++
lkwq007 Python
lzl124631x C++
ruoru Rust
suxrobGM C#
trung-hn Python
zfang399 C++
AlgoMonster C++, Python, Java, TypeScript
WalkCCC C++, Python, Java
leetcode.ca C++, Go, Java, Python
LeetcodeHelp C++, Java, Python
Progiez C++, Java, Python
BigEggStudy C#
black-shadows C++, C++
charles-wangkai Java
everthis JavaScript
halfrost Go
JoshCrozier JavaScript
keineahnung2345 C++
lkwq007 Python
lzl124631x C++
ruoru Rust
suxrobGM C#
trung-hn Python
zfang399 C++
30 links | 18 authors | 8 languages

Videos

3 videos   did my crawler come up with invalid videos ? drop me a line.

Solved On The Same Day

8 solutions   November 30, 2023

Extra

There are a few extra pages giving you some insights into my setup:
  • Tech Stack - my development environment and tools
  • AI - how AI helped me create this website (NOT solving the problems)
  • Progress - progression over time
  • Quality - code quality