Cómo contar grupos de números enteros dentro de las matrices, sin ordenar la matriz?

Harsh Patel:

Mi objetivo es ser capaz de contar grupos del mismo número entero dentro de una matriz. Por ejemplo, en una matriz como tal, {1, 1, 1, 2, 2, 3, 1, 1}hay 4 grupos :

  • de al menos el tamaño de 1: 3 grupos
  • de al menos el tamaño de 2: 1 grupo
  • de al menos el tamaño de 3

Tengo problemas Lograr esto sin ordenar la matriz. Cuando se ordena que pierde la cuenta del grupo de dos de 1 al final de la serie, ya que se puso al lado de los otros grupos de 1 de.

int result = (int) Stream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6)
        .collect(Collectors.groupingBy(i -> i))
        .entrySet().stream()
        .filter(entry -> entry.getValue().size() >= 1) // specify the size
        .count()

return result;

Esta salida se espera para cada tamaño es el siguiente:

size 1 count == 8

size 2 count == 5

size 6 count == 1

size 8 count == 1

La salida real es la siguiente:

size 1 count == 6

size 2 count == 3

size 6 count == 2

size 8 count == 1

La diferencia es el resultado del ser matriz ordenada antes de la toma de recuento lugar. ¿Hay alguna forma de lograr esto?

Editar: grupo A es esencialmente cualquier lugar donde las mismas repeticiones enteros, hasta un número entero de un valor diferente, es por delante de él; Por lo tanto, los grupos de tamaño 2 en este en este código son cualquier en el índice 0 a 2 (inclusive), índice de 4 - 5 (inclusive), índice de 6 - 15 (inclusive, índice de 16 - 18 (inclusive, y el índice de 20 -22 (inclusive). Puesto que hay 5 grupos que son de al menos el tamaño 2 un recuento de 5 debe ser devuelto.

Un estilo imperativo de código para mi objetivo.

Scanner key = new Scanner("1 1 1 2 1 1 3 3 3 3 3 3 3 3 3 3 4 4 4 5 4 4 4 6");

        int cnt = 0;
        int counter = 0;
        int i = 0;

            while(key.hasNextInt()) {   
                int next = key.nextInt();

                if(next == array[i]) {
                    counter++;
                }

                if(i + 1 < array.length && i -1 >= 0 
                   && counter >=size  
                   && next != array[i + 1] 
                   && next == array[i-size + 1]) {
                    cnt++;
                    counter = 0;
                }
                i++;
            }
        return cnt;

El rendimiento esperado de esto es el mismo que el anterior.

El rendimiento real es:

size 1 count == 7

size 2 count == 5

size 6 count == 3

size 8 count == 1

El problema con este bucle es creo que está saltando primera pieza y la pieza final de la matriz.

No estoy teniendo el mismo problema de clasificación como la Corriente del camino.

Idealmente, esto no requeriría ningún utilidades / bibliotecas externas .

Samuel Philipp:

En primer lugar yo sugeriría para encontrar todos los subgrupos. Para ello se puede utilizar Stream.collect()con un colector de encargo:

List<List<Integer>> sublists = IntStream.of(1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 4, 4, 4, 6)
        .collect(ArrayList::new, (lists, value) -> {
            if (lists.isEmpty() || lists.get(lists.size() - 1).stream().noneMatch(e -> e == value)) {
                lists.add(new ArrayList<>());
            }
            lists.get(lists.size() - 1).add(value);
        }, (l1, l2) -> {
            throw new RuntimeException("not supported for parallel streams");
        });

El resultado es:

[[1, 1, 1], [2], [1, 1], [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [4, 4, 4], [5], [4, 4, 4], [6]]

Ahora se puede utilizar para agrupar los tamaños de la lista:

Map<Integer, Long> result = sublists.stream()
        .collect(Collectors.groupingBy(List::size, Collectors.counting()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));

Esto encuentra todos los tamaños y las impresiones de grupo existentes:

size 1 count 3
size 2 count 1
size 3 count 3
size 10 count 1

Para contar todos los grupos con una longitud min puede utilizar:

Map<Integer, Long> result = IntStream.rangeClosed(1, sublists.stream().mapToInt(List::size).max().orElse(0)).boxed()
        .collect(Collectors.toMap(Function.identity(), i -> sublists.stream().filter(l -> l.size() >= i).count()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));

Esta impresora:

size 1 count 8
size 2 count 5
size 3 count 4
size 4 count 1
size 5 count 1
size 6 count 1
size 7 count 1
size 8 count 1
size 9 count 1
size 10 count 1

Para obtener únicamente un conjunto predefinido de tamaños (por ejemplo 1, 2, 6, 8) puede modificar la última solución:

Map<Integer, Long> result = IntStream.of(1, 2, 6, 8).boxed()
        .collect(Collectors.toMap(Function.identity(), i -> sublists.stream().filter(l -> l.size() >= i).count()));
result.forEach((size, count) -> System.out.println(String.format("size %s count %s", size, count)));

El resultado de esto es:

size 1 count 8
size 2 count 5
size 6 count 1
size 8 count 1

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=180154&siteId=1
Recomendado
Clasificación