Single-pass algorithm without recursion:
We touch the elements from left to right and from top to bottom. Having met the value 1, we replace it, for example, with 11. Then, in the process of searching, having found the value 1, which borders on 11, we replace it by 11, and if it does not, then by 12, etc. As a result, we call each group its unique number. In parallel, in a separate array, we count how many times we changed 1 to the value of the named group. Most likely, conflicts will arise like the fact that different βnamesβ were assigned to the same group. It is necessary to simultaneously identify such conflicts. The conflict is resolved by maintaining the third array of "synonyms". If we have 1, which borders on, for example, 11 and 12, then we assume that 11 and 12 are the same group.
Code implementing algorithm:
public class Test3 { public static void main(String[] args) { int[][] matrix = { { 0,1,1,0,1,0,0,1 }, { 0,0,1,1,1,1,0,1 }, { 1,1,0,1,0,0,1,1 }, { 1,0,1,0,1,1,0,1 } }; getMatrixGroupsFrom01( matrix ); } public static void getMatrixGroupsFrom01( int[][] matrix ) { int width = matrix[0].length; int height = matrix.length; int groupsCount = 10; // first group - 11, second - 12 ... int group1, group2; HashMap<Integer,Integer> groupsLength = new HashMap<Integer,Integer>(); HashMap<Integer,List<Integer>> synonims = new HashMap<Integer,List<Integer>>(); List<Integer> currentSyn; for ( int i = 0; i < width; i++ ) { for ( int j = 0; j < height; j++ ) { if ( matrix[j][i] == 1 ) { // Π΅ΡΠ»ΠΈ ΡΠ΅ΠΊΡΡΠ°Ρ ΡΡΠ΅ΠΉΠΊΠ° ΠΏΡΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ ΠΏΠΎΠΊΠ° Π½Π΅ΠΈΠ·Π²Π΅ΡΡΠ½ΠΎΠΉ Π³ΡΡΠΏΠΏΠ΅ group1 = group2 = 0; // ΡΠ±ΡΠΎΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ if ( j>0 && matrix[j-1][i]>0 ) group1 = matrix[j-1][i]; // Π³ΡΡΠΏΠΏΠ° ΡΠ²Π΅ΡΡ
Ρ if ( i>0 && matrix[j][i-1]>0 ) group2 = matrix[j][i-1]; // Π³ΡΡΠΏΠΏΠ° ΡΠ½ΠΈΠ·Ρ if ( group1 == 0 && group2 == 0 ) { // Π΅ΡΠ»ΠΈ ΠΎΠΊΡΡΠΆΠ°ΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π½ΡΠ»ΠΈ, ΡΠΎ Π½Π°Π΄ΠΎ Π·Π°Π΄Π°ΡΡ Π½ΠΎΠ²ΡΡ Π³ΡΡΠΏΠΏΡ groupsCount++; // Π½ΠΎΠ²ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π³ΡΡΠΏΠΏΡ matrix[j][i] = groupsCount; groupsLength.put( groupsCount, 1 ); } else if ( group1 == 0 || group2 == 0 || group1 == group2 ) { // Π΅ΡΠ»ΠΈ Π³ΡΡΠΏΠΏΡ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ ΠΈΠ»ΠΈ ΠΎΠ΄Π½Π° ΠΈΠ· Π½ΠΈΡ
ΡΠ°Π²Π½Π° 0 matrix[j][i] = group1 == 0 ? group2 : group1; groupsLength.put( matrix[j][i], groupsLength.get( matrix[j][i] )+1 ); // ΠΈΠ½ΠΊΡΠ΅ΠΌΠ΅Π½Ρ } else { // Π΅ΡΠ»ΠΈ Π³ΡΡΠΏΠΏΡ ΡΠ°Π·Π½ΡΠ΅, ΡΠΎ Π΅ΡΡΡ ΠΊΠΎΠ½ΡΠ»ΠΈΠΊΡ. ΠΠΎΠ½ΡΠ»ΠΈΠΊΡ Π½ΡΠΆΠ½ΠΎ ΡΠ°Π·ΡΠ΅ΡΠΈΡΡ ΡΠΎΠ·Π΄Π°Π² ΡΠΈΠ½ΠΎΠ½ΠΈΠΌ if ( group1 > group2 ) { // ΡΡΠΎΠ±Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΠΏΠΎΡΠΎΠΌ Ρ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΡΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ int swap = group2; group2 = group1; group1 = swap; } //System.out.println( group1 + " " + group2 ); if ( synonims.containsKey( group1 ) ) { currentSyn = synonims.get( group1 ); } else { currentSyn = new ArrayList<Integer>(); } if ( currentSyn.indexOf( group2 ) == -1 ) { // Π΅ΡΠ»ΠΈ ΡΠ°ΠΊΠΎΠ³ΠΎ ΡΠΈΠ½ΠΎΠ½ΠΈΠΌΠ° Π΅ΡΠ΅ Π½Π΅Ρ currentSyn.add( group2 ); } synonims.put(group1, currentSyn); // ΡΠΎΠ·Π΄Π°Π΅ΠΌ ΡΠΈΠ½ΠΎΠ½ΠΈΠΌ matrix[j][i] = group1; groupsLength.put( group1, groupsLength.get( group1 )+1 ); // ΠΈΠ½ΠΊΡΠ΅ΠΌΠ΅Π½Ρ } } System.out.print( matrix[j][i] + "\t" ); } System.out.print( "\n" ); } // Ρ ΡΡΠΎΠ³ΠΎ ΠΌΠΎΠΌΠ΅Π½ΡΠ° Π΅ΡΡΡ ΠΈΡΡΠ΅ΡΠΏΡΠ²Π°ΡΡΠΈΠ΅ Π΄Π°Π½Π½ΡΠ΅ ΠΎ Π³ΡΡΠΏΠΏΠ°Ρ
int synSize = synonims.size(); Integer[] s = {}; s = synonims.keySet().toArray( s ); for ( int i=0; i < synSize; i++ ) { // ΠΏΠ΅ΡΠ΅Π±ΠΈΡΠ°Π΅ΠΌ ΡΠΈΠ½ΠΎΠ½ΠΈΠΌΡ System.out.print( "\n" + s[i] + " => " ); List<Integer> sd = synonims.get( s[i] ); Iterator<Integer> cs = sd.iterator(); while ( cs.hasNext() ) { int synVal = cs.next(); System.out.print( synVal + " " ); groupsLength.put( s[i], groupsLength.get( s[i] ) + groupsLength.get( synVal ) ); // Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΠΊ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΡΠΌΠΌΠ΅ ΡΡΠΌΠΌΡ ΡΠΈΠ½ΠΎΠ½ΠΈΠΌΠ° groupsLength.remove( synVal ); // ΡΠ΄Π°Π»ΡΠ΅ΠΌ ΡΠΈΠ½ΠΎΠ½ΠΈΠΌΠΈΡΠ½ΡΡ ΡΡΠΌΠΌΡ } } System.out.println( "\n" ); s = groupsLength.keySet().toArray( s ); for ( int i = 0; i < s.length; i++ ) { System.out.println( "Group:\t" + s[i] + "\tSize: " + groupsLength.get( s[i] ) ); } } }
Result of work:
0 0 11 11 12 0 11 0 12 12 0 13 0 12 12 0 14 12 0 15 0 12 0 15 0 0 16 0 17 17 16 16 16 => 17 12 => 14 Group: 16 Size: 5 Group: 11 Size: 3 Group: 12 Size: 8 Group: 13 Size: 1 Group: 15 Size: 2
To bring beauty inside the matrix, we need another pass, in which synonyms are replaced by one value, but for the tasks posed in the question, beauty is not needed.