given an n*m matrix with the possible values of 1, 2 and null:
. . . . . 1 . .
. 1 . . . . . 1
. . . 2 . . . .
. . . . 2 . . .
1 . . . . . 1 .
. . . . . . . .
. . 1 . . 2 . .
2 . . . . . . 1
I am looking for all blocks B (containing all values between (x0,y0) and (x1,y1)) that:
- contain at least one ‘1’
- contain no ‘2’
- are not a subset of a another block with the above properties
Example:

The red, green and blue area all contain an ‘1’, no ‘2’, and are not part of a larger area.
There are of course more than 3 such blocks in this picture. I want to find all these blocks.
what would be a fast way to find all these areas?
I have a working brute-force solution, iterating over all possible rectangles, checking if they fulfill the first two criteria; then iterating over all found rectangles, removing all rectangles that are contained in another rectangle; and I can speed that up by first removing consecutive identical rows and columns. But I am fairly certain that there is a much faster way.
I finally found a solution that works almost in linear time (there is a small factor depending on the number of found areas). I think this is the fastest possible solution.
Inspired by this answer: https://stackoverflow.com/a/7353193/145999 (pictures also taken from there)
First, I go trought the matrix by column, creating a new matrix M1 measuring the number of steps to the last ‘1’ and a matrix M2 measuring the number of steps to the last ‘2’

imagine a ‘1’ or ‘2’ in any of the grey blocks in the above picture
in the end I have M1 and M2 looking like this:
No go through M1 and M2 in reverse, by row:
I execute the following algorithm:
now foundAreas contains all rectangles with the desired properties.