How can I find hole in a 2D matrix?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
In a binary matrix, a "hole" usually means a region of empty cells that is completely enclosed by filled cells. The standard way to find holes is not to search for enclosed regions directly, but to mark every empty cell that can reach the boundary. Any empty cell left unmarked afterward belongs to a hole.
Define the Connectivity Rule First
Before writing code, decide what counts as connected:
- four-directional connectivity using up, down, left, and right
- eight-directional connectivity including diagonals
Most grid problems default to four-directional connectivity unless the problem statement says otherwise. The answer can change depending on that rule.
The Key Insight
A hole cannot touch the outer border of the matrix. So instead of starting from interior cells, start from all boundary zero cells and flood-fill outward through connected zero cells. Those cells are not holes because they can escape to the boundary.
After that flood fill:
- visited zero cells are outside or boundary-connected space
- unvisited zero cells are enclosed holes
This gives a linear-time algorithm.
Breadth-First Search Solution
Here is a Python implementation using breadth-first search.
This returns the coordinates of all zero cells that belong to holes.
Finding Separate Hole Regions
Sometimes you do not just want the cells. You want each hole as its own connected component. In that case, do a second flood fill over the remaining unvisited zero cells.
This groups enclosed zero cells into separate holes.
Complexity
The algorithm visits each cell at most a constant number of times, so the time complexity is O(rows * cols). The extra memory is also O(rows * cols) if you store visited state separately.
That is about as good as it gets for a general matrix scan because you must at least inspect the grid.
Common Pitfalls
The biggest pitfall is trying to decide whether each zero is a hole using only local neighbors. Hole detection is global. A zero may look enclosed nearby but still connect to the boundary through a longer path.
Another issue is forgetting to define connectivity. Four-directional and eight-directional rules can produce different answers.
Developers also mutate the original matrix too early and then lose track of which cells were originally empty. That is fine if done intentionally, but use a separate visited structure when clarity matters more than in-place optimization.
Finally, watch out for edge cases such as empty grids, one-row grids, or one-column grids where no interior hole can exist under the usual definition.
Summary
- A hole is an empty region that cannot reach the boundary.
- Flood-fill from boundary empty cells first, then treat the remaining empty cells as holes.
- Use BFS or DFS; both work with the same idea.
- Decide whether connectivity is four-directional or eight-directional before coding.
- The standard approach runs in linear time over the size of the matrix.
Related reading
- How can I find the actual path found by BFS?
- How can I find the best fit subsequences of a large string?
- How can I find the maximum sum of a sub-sequence using dynamic programming?
- How can I find the minimal circle include some given points?
- How can I find the number of Hamiltonian cycles in a complete undirected graph?
- How can I fit a Bézier curve to a set of data?
- How can I find the shortest path between 100 moving targets? Live demo included.
- How can I find the time complexity of an algorithm?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.