How can I find hole in a 2D matrix?

后端 未结 5 2193
死守一世寂寞
死守一世寂寞 2020-12-14 09:30

I know the title seems kind of ambiguous and for this reason I\'ve attached an image which will be helpful to understand the problem clearly. I need to find holes inside the

5条回答
  •  盖世英雄少女心
    2020-12-14 09:48

    Your algorithm is globally Ok. It's just a matter of optimizing it by merging the flood fill exploration with the cell scanning. This will just minimize tests.

    The general idea is to perform the flood fill exploration line by line while scanning the table. So you'll have multiple parallel flood fill that you have to keep track of.

    The table is then processed row by row from top to bottom, and each row processed from right to left. The order is arbitrary, could be reverse if you prefer.

    Let segments identify a sequence of consecutive cells with value 0 in a row. You only need the index of the first and last cell with value 0 to define a segment. As you may guess a segment is also a flood fill in progress. So we'll add an identification number to the segments to distinguish between the different flood fills.

    The nice thing of this algorithm is that you only need to keep track of segments and their identification number in row i and i-1. So that when you process row i, you have the list of segments found in the row i-1 and their associated identification number.

    You then have to process segment connection in row i and row i-1. I'll explain below how this can be made efficient.

    For now you have to consider three cases:

    1. found a segment in row i not connected to a segment in row i-1. Assign it a new hole identification (incremented integer). If it's connected to the border of the table, make this number negative.

    2. found a segment in row i-1 not connected to a segment in row i-1. You found the lowest segment of a hole. If it has a negative identification number it is connected to the border and you can ignore it. Otherwise, congratulation, you found a hole.

    3. found a segment in row i connected to one or more segments in row i-1. Set the identification number of all these connected segments to the smallest identification number. See the following possible use case.

    row i-1:   2  333 444 111
    row i  :  ****  *** ***
    

    The segments in row i should all get the value 1 identifying the same flood fill.

    Matching segments in rows i and row i-1 can be done efficiently by keeping them in order from left to right and comparing segments indexes.

    Process segments by lowest start index first. Then check if it's connected to the segment with lowest start index of the other row. If no, process case 1 or 2. Otherwise continue identifying connected segments, keeping track of the smallest identification number. When no more connected segments is found, set the identification number of all connected segments found in row i to the smallest identification value.

    Index comparison for connectivity test can by optimized by storing (first-1,last) as segment definition since segments may be connected by their corners. You then can directly compare indexes bare value and detect overlapping segments.

    The rule to pick the smallest identification number ensures that you automatically get the negative number for connected segments and at least one connected to the border. It propagates to other segments and flood fills.

    This is a nice exercise to program. You didn't specify the exact output you need. So this is also left as exercise.

提交回复
热议问题