简体   繁体   中英

Get largest and smallest group of ones in binary array

I have a 2D array of 0's and 1's.

Every consecutive cells having 1's is considered as single object.

My task is to find the largest consecutive 1's for every row and also smallest consecutive 1's and get the difference of those.

Example:

oth Row --> 0 0 0 0 0
1st Row --> 0 0 1 0 0 
2nd Row --> 0 0 1 0 1
3rd Row --> 1 1 1 0 1 
4th Row --> 0 0 0 0 0 

Explanation:

In 0th Row there are no 1's so no operation needed.

In 1st Row there is a single 1, so I am considering it as largest object of this row is 1.

In 2nd Row there is a 1 at position [2,2], I am considering it as largest object of this row is 1. Now the next 1 at position [2, 4], I am considering it as smallest object of this row is 1.

In 3rd Row there are three 1's at position [3,0],[3,1],[3,2], I am considering it as largest object of this row is 3. Now the next 1 at position [3, 4], I am considering it as smallest object of this row is 1.

In 4th row there are no 1's so no operation needed.

My task is to find the difference between the sum all largest objects and sum of all smallest objects.

In this example:

Sum of largest objects = 0 (0th row) + 1 (1st row) + 1 (2nd row) + 3 (3rd row) + 0 (4th row) = 5
Sum of smallest objects = 0 (0th row) + 0 (1st row) + 1 (2nd row) + 1 (3rd row) + 0 (4th row) = 2

Result = sum of largest - sum of smallest = 5 - 2 = 3.

I have comeup with below logic:

public static int process(int[][] array)
{
    int result = 0;
    // Get row and column size
    int rows = array.length;
    int cols = array[0].length;

    // variables to store sum of large and small objects
    int large = 0;
    int small = 0;

    for(int i=0; i<rows; i++) {
        // variables to store large and small objects per row level
        int l_count = 0;
        int s_count = 0;


        boolean valid = false;
        for(int j=0; j<cols-1; j++) {
            int curr = array[i][j];
            int next = array[i][j+1];
            // First occurrence of 1 is considered as large object
            if(l_count == 0 && curr == 1) {
                l_count++;
                valid = true;
            }
            // consecutive 1's added to large count
            if(valid && curr == next) {
                l_count++;
            } else {
                valid = false;
            }

            // Get small count
            if(!valid && curr == 1 || next == 1) {
                s_count++;
            }
        }
        // Add row level counts to large and small objects
        large += l_count;
        small += s_count;

    }
    result = large - small;
  return result;
}

This is not working and giving wrong results, I am not able to find the needed logic to solve this problem.

To find the largest and smallest objects in each row you might first want to get a list of all objects in the row, then filter accordingly, that is have a function that does

0 0 0 0 0 -> []
0 0 1 0 0 -> [1]
0 0 1 0 1 -> [1,1]
1 1 1 0 1 -> [3,1]
0 0 0 0 0 -> []

After that you can use a function such as Collections.max(collection) and Collections.min(Collection) to get the maximum and minimum values. To account for the case in row 1 you could then check if(foundObjects.size < 2) and set min to 0 in that case.

A possible implementation for this, assuming you are using Java 1.8 or newer would be the following:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

class ObjectCalculator {
    static int compute(int[][] array){
        return Arrays.stream(array)
                .map(ObjectCalculator::findObjects)
                .mapToInt(objects -> {
                    int min, max;
                    if (objects.size() < 2) min = 0;
                    else min = Collections.min(objects);
                    if (objects.size() < 1) max = 0;
                    else max = Collections.max(objects);
                    return max - min;
                }).sum();
    }

    static List<Integer> findObjects(int[] array) {
        ArrayList<Integer> objects = new ArrayList<>();
        int curSize = 0;
        for(int i : array){
            if(i == 1)curSize++;
            else if(curSize > 0){
                objects.add(curSize);
                curSize = 0;
            }
        }
        if(curSize > 0){
            objects.add(curSize);
        }
        return objects;
    }
}

Perhaps the changes below could solve your problem. Do not look over to the next element, just keep a count and keep working with the current element always.

public static int process(int[][] array)
{
    int result = 0;
    // Get row and column size
    int rows = array.length;
    int cols = array[0].length;

    // variables to store sum of large and small objects
    int large = 0;
    int small = 0;

    for(int i=0; i<rows; i++) {
        // variables to store large and small objects per row level
        int l_count = 0;
        int s_count = 0;
        int count = 0;

        for(int j=0; j<cols; j++) {
            if (array[i][j]) {
                count++;
            } else if (count > 0) {
                if (count > l_count) {
                    l_count = count;
                } else if (count < s_count || s_count == 0) {
                    s_count = count;
                }
                count = 0;
            }
        }
        // Add row level counts to large and small objects
        large += l_count;
        small += s_count;

    }
    result = large - small;
  return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM