#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
пар.