Подсчитайте, сколько пар чисел появляется в массиве

#java #hashtable

Вопрос:

Допустим, с массивом:

 array = {1,2,1,2,1,3,2,1};
 

Я хочу, чтобы результат был:

 2 pairs of number 1, 1 pair of number 2
 

Для этого я создал хэш-таблицу. Код :

 class Trail{
    static void countFreq(int arr[], int n)
    {
        Map<Integer, Integer> mp = new HashMap<>();
 
        // Insert elements into HashTable while avoiding overwriting:
        for (int i = 0; i < n; i  )
        {
            // This part is to avoid overwriting:
            if (mp.containsKey(arr[i]))
            {
                mp.put(arr[i], mp.get(arr[i])   1);
            }
            else
            {
                mp.put(arr[i], 1);
            }
        }
        // Traverse through map and print frequencies
        for (Map.Entry<Integer, Integer> entry : mp.entrySet())
        { 
            System.out.println(entry.getKey()   " "   entry.getValue());
            
        }
         
    }

    public static void main(String[] args) {

        int arr[] = {1,2,1,2,1,3,2,1};
        int n = arr.length;
        countFreq(arr, n);
    }
}
 

Не уверен, что делать дальше, чтобы распечатать желаемый результат. Я надолго застрял в этой простой части.

Ответ №1:

Расчет частот, кажется, в порядке, нужно решить только часть печати. Чтобы получить количество пар, разделите частоту на 2 (или сдвиньте вправо на 1) и пропустите, если количество пар равно 0 (в соответствии с ожидаемым результатом).

Печать следует перенести в отдельный метод:

 static void printFreq(Map<Integer, Integer> mp) {
    boolean addComma = false;
    for (Map.Entry<Integer, Integer> entry : mp.entrySet()) {
        int pairs = entry.getValue() / 2;
        if (pairs < 1) {
            continue; // skip 0 pairs
        }
        if (addComma) {
            System.out.print(", ");
        }
        String p = pairs > 1 ? " pairs " : " pair ";
        System.out.print(pairs   p   "of number "   entry.getKey());
        addComma = true;
    }        
    System.out.println();    
}
 

Однако для таких задач может использоваться API потока:

  • используйте vararg int ... arr для более удобной передачи массива целочисленных значений ( так n как длина массива избыточна)
  • используйте Collectors.groupingBy и Collectors.summingInt (или Collectors.counting ) для расчета необработанной частоты
  • вычислите количество пар
  • сопоставьте каждую пару ключ-значение в строку
  • присоединяйтесь к строкам с помощью коллекторов.
 static void countFreq(int ... arr) {
    String message = Arrays.stream(arr)
        .boxed()
        .collect(Collectors.groupingBy(
            x -> x,
            Collectors.summingInt(x -> 1)
        )) // Map<Integer, Integer>
        .entrySet()
        .stream()
        .peek(e -> e.setValue(e.getValue() / 2))
        .filter(e -> e.getValue() > 0)
        .map(e -> String.format("%d %s of number %d", 
            e.getValue(), e.getValue() > 1 ? "pairs" : "pair", e.getKey()
        ))
        .collect(Collectors.joining(", "));
    System.out.println(message);
}
 

Выходные данные (в обоих случаях):

 2 pairs of number 1, 1 pair of number 2
 

Комментарии:

1. Большое спасибо, это работает как шарм!

Ответ №2:

Было бы проще всего сделать это с помощью a Map<Integer, Long> и выполнить подсчет частоты.

  • потоковая передача массива
  • поместите его в рамку (преобразуйте в целочисленный объект)
  • группируйте на основе значения a
  • и подсчитайте появление этого значения
  • на карте k указано значение и v количество
  • логика также добавлена для исправления множественности чисел.
 int[] vals  = {1,2,1,2,1,3,2,1};
Arrays.stream(vals).boxed().collect(
        Collectors.groupingBy(a -> a, Collectors.counting()))
        .forEach((k, v) -> {
            if (v > 1) {
                System.out.println(v / 2   " pair"
                          ((v > 3) ? "s" : "")   " of "   k);
            }
        });
 

С принтами

 2 pairs of 1
1 pair of 2

 

Обратите внимание, что при этом используется преимущество целочисленного деления и отбрасывается дробь. Таким образом, любое нечетное число n будет иметь значение (n-1)/2 пар.