554. Brick Wall - Explanation

Problem Link



Prerequisites

Before attempting this problem, you should be comfortable with:

  • Hash Map - Using hash maps to count frequencies and find the most common element efficiently
  • Prefix Sum - Computing cumulative sums to track edge positions between bricks

1. Brute Force

Intuition

The goal is to draw a vertical line through the wall that crosses the fewest bricks. A line crosses a brick only if it doesn't pass through a gap between bricks. So we need to find the vertical position where the most gaps align across all rows.

The brute force approach is straightforward: for every possible vertical position (from 1 to wall width minus 1), count how many rows do NOT have a gap at that position. The position with the fewest cuts is our answer.

Algorithm

  1. Calculate the total width of the wall by summing the bricks in the first row.
  2. For each row, compute the cumulative positions where gaps exist (edges between bricks).
  3. For each possible vertical line position from 1 to width - 1:
    • Count how many rows do not have a gap at this position (these are the bricks that would be cut).
    • Track the minimum number of cuts found.
  4. Return the minimum cut count.
class Solution:
    def leastBricks(self, wall: List[List[int]]) -> int:
        n = len(wall)
        m = 0
        for brick in wall[0]:
            m += brick

        gaps = [[] for _ in range(n)]
        for i in range(n):
            gap = 0
            for brick in wall[i]:
                gap += brick
                gaps[i].append(gap)

        res = n
        for line in range(1, m):
            cuts = 0
            for i in range(n):
                if line not in gaps[i]:
                    cuts += 1

            res = min(res, cuts)
        return res

Time & Space Complexity

  • Time complexity: O(mng)O(m * n * g)
  • Space complexity: O(ng)O(n * g)

Where mm is the sum of widths of the bricks in the first row, nn is the number of rows and gg is the average number of gaps in each row.


2. Hash Map

Intuition

Instead of checking every possible vertical position, we can think about this differently. We want to maximize the number of gaps we pass through, because each gap means we avoid cutting a brick. If we count how many times each gap position appears across all rows, the position with the most gaps is the best place to draw our line. The answer is then total rows minus the maximum gap count.

Algorithm

  1. Use a hash map to count the frequency of each gap position across all rows.
  2. For each row, compute cumulative brick widths (excluding the last brick to avoid counting the wall edge).
  3. For each cumulative width, increment its count in the hash map.
  4. Find the maximum count in the hash map (the position with the most aligned gaps).
  5. Return the total number of rows minus this maximum count.
class Solution:
    def leastBricks(self, wall: List[List[int]]) -> int:
        countGap = {0: 0}

        for r in wall:
            total = 0
            for i in range(len(r) - 1):
                total += r[i]
                countGap[total] = 1 + countGap.get(total, 0)

        return len(wall) - max(countGap.values())

Time & Space Complexity

  • Time complexity: O(N)O(N)
  • Space complexity: O(g)O(g)

Where NN is the total number of bricks in the wall and gg is the total number of gaps in all the rows.


Common Pitfalls

Counting the Wall Edge as a Valid Gap

The rightmost edge of the wall (at position equal to total width) should not be counted as a gap since a line there wouldn't cross any bricks anyway. Including it inflates the gap count and gives wrong answers.

# Wrong: counting all gaps including the last one
for brick in row:
    total += brick
    countGap[total] += 1  # Counts wall edge

# Correct: exclude the last brick
for i in range(len(row) - 1):
    total += row[i]
    countGap[total] += 1

Returning Maximum Gaps Instead of Minimum Cuts

The answer is number_of_rows - max_gaps, not just max_gaps. Maximizing gaps minimizes cuts, but forgetting to subtract from total rows returns the wrong value.

Not Handling Rows with Single Bricks

If a row contains only one brick spanning the entire width, it has no internal gaps. The hash map initialization with {0: 0} handles the edge case where no gaps exist, ensuring the answer defaults to cutting through all rows.