554. Brick Wall - Explanation
Description
There is a rectangular brick wall in front of you with n rows of bricks. The i-th row has some number of bricks each of the same height (i.e., one unit) but they can be of different widths. The total width of each row is the same.
Draw a vertical line from the top to the bottom and cross the least bricks. If your line goes through the edge of a brick, then the brick is not considered as crossed. You cannot draw a line just along one of the two vertical edges of the wall, in which case the line will obviously cross no bricks.
Given the 2D array wall that contains the information about the wall, return the minimum number of crossed bricks after drawing such a vertical line.
Example 1:
Input: wall = [[1,2,2,1],[3,1,2],[1,3,2],[2,4],[3,1,2],[1,3,1,1]]
Output: 2Example 2:
Input: wall = [[1],[1],[1]]
Output: 3Constraints:
n == wall.length1 <= n <= 10,0001 <= wall[i].length <= 10,0001 <= sum(wall[i].length) <= 20,000sum(wall[i])is the same for each rowi.1 <= wall[i][j] <= ((2^31) - 1)
Topics
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
- Calculate the total width of the wall by summing the bricks in the first row.
- For each row, compute the cumulative positions where gaps exist (edges between bricks).
- For each possible vertical line position from
1towidth - 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.
- 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 resTime & Space Complexity
- Time complexity:
- Space complexity:
Where is the sum of widths of the bricks in the first row, is the number of rows and 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
- Use a hash map to count the frequency of each gap position across all rows.
- For each row, compute cumulative brick widths (excluding the last brick to avoid counting the wall edge).
- For each cumulative width, increment its count in the hash map.
- Find the maximum count in the hash map (the position with the most aligned gaps).
- Return the total number of rows minus this maximum count.
Time & Space Complexity
- Time complexity:
- Space complexity:
Where is the total number of bricks in the wall and 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] += 1Returning 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.
Sign in to join the discussion