我应该“编写一个方法,打印出数组中最常见的前5个数字,以及每个数组的出现次数”,我有一个方法,它输出数组中每个条目的出现情况,并创建了另一个方法来打印数组中最常见的5个数字。我能够按降序正确地显示值,但我很难获得同样的键。例如,我的数组是7、8、5、3、9、3、3、9、4、7、3、6、9、3、2、9、6、5、7、6、3、3和3。对于top5方法,我的输出是"2 :5:5:4:3:3:5:3:6:2“,当它应该是"3 :5:9:4:6:3:3:5:2”时,我如何才能修复我的方法以获得预期的输出?
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Random;
public class HW4 {
public static void main(String[] args) {
int[] a = getRandom(20, 1, 10);
System.out.println(Arrays.toString(a));
System.out.println();
occurrence(a);
System.out.println();
top5(a);
}
public static int[] getRandom(int n, int low, int high) {
long seed = 0;
Random random = new Random(seed);
random.setSeed(seed);
int[] result = new int[n];
for (int i = 0; i < n; i++)
result[i] = random.nextInt(high - low) + low;
return result;
}
public static void occurrence(int[] x) {
HashMap<Integer, Integer> occurrences = new HashMap<>();
for (int key : x) {
if (occurrences.containsKey(key)) {
occurrences.put(key, occurrences.get(key) + 1);
} else {
occurrences.put(key, 1);
}
}
for (int key : occurrences.keySet()) {
System.out.println(key + " occurs: " + occurrences.get(key) + " times");
}
}
public static void top5(int[] arr) {
HashMap<Integer, Integer> lookup = new HashMap<Integer, Integer>();
for (int key : arr) {
if (lookup.containsKey(key)) {
lookup.put(key, lookup.get(key) + 1);
} else {
lookup.put(key, 1);
}
}
ArrayList<Integer> keys = new ArrayList<>(lookup.keySet());
ArrayList<Integer> values = new ArrayList<>(lookup.values());
for (int i = 0; i < 5; i++) {
Collections.sort(values, Collections.reverseOrder());
System.out.println(keys.get(i) + " occurs: " + values.get(i) + " times");
}
}
}发布于 2022-09-17 18:33:43
public static void top5(int[] arr) {
IntStream.of(arr).boxed()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream()
.sorted((e1, e2) -> Long.compare(e2.getValue() , e1.getValue()))
.limit(5)
.forEach(e -> System.out.printf("%d occurs %d times%n", e.getKey(), e.getValue()));
}前两行创建直方图,即映射每个值到其出现次数的地图。下一行将获得条目流,该流将按其值(即发生的数量)进行反向排序。您只需要5个元素,因此结果被限制为5,最后一行的结果被很好地格式化。
发布于 2022-09-17 19:08:30
条目列表+排序
最简单的方法是使用HashMap计算数组中每个数字的频率,就像您所做的那样。
然后将所有映射项转储到列表中,并按值对列表进行排序。我们需要一个Comparator来执行这个排序。为此,我们可以使用Java 8方法Map.Entry.comparingByValue()获得一个比较器。
作为最后一步,打印第一个5元素。
public static void top5(int[] arr) {
Map<Integer, Integer> lookup = new HashMap<>();
for (int key : arr) {
int value = lookup.getOrDefault(key, 0); // or lookup.merge(key, 1, Integer::sum); instead of these two lines
lookup.put(key, value + 1);
}
List<Map.Entry<Integer, Integer>> sortedEntries = new ArrayList<>(lookup.entrySet());
sortedEntries.sort(Map.Entry.<Integer, Integer>comparingByValue().reversed());
for (int i = 0; i < 5; i++) {
System.out.println(
sortedEntries.get(i).getKey() + " occurs: " +
sortedEntries.get(i).getValue() + " times"
);
}
}PriorityQueue
与其对整个数据进行排序,更好的方法是使用PriorityQueue。
第一步保持不变-生成一个频率图。
下一步是创建一个存储地图条目的PriorityQueue。为此,我们还需要一个比较国。
然后遍历条目集,尝试将每个条目提供给队列。如果队列的大小等于5,且下一个条目的值大于队列中最低值的值(即PriorityQueue的根元素的值),则需要删除队列的根元素。只要队列有空闲空间(如果队列大小小于5),就应该将下一个条目添加到队列中。
以下是它的实现方式:
public static void top5(int[] arr) {
Map<Integer, Integer> lookup = new HashMap<>();
for (int key : arr) {
int value = lookup.getOrDefault(key, 0); // or lookup.merge(key, 1, Integer::sum); instead of these two lines
lookup.put(key, value + 1);
}
Queue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>(
Map.Entry.comparingByValue()
);
for (Map.Entry<Integer, Integer> entry: lookup.entrySet()) {
if (queue.size() == 5 && queue.peek().getValue() < entry.getValue()) queue.poll();
if (queue.size() < 5) queue.offer(entry)
}
while (!queue.isEmpty()) {
Map.Entry<Integer, Integer> next = queue.poll();
System.out.println(
next.getKey() + " occurs: " +
next.getValue() + " times"
);
}
}发布于 2022-09-17 17:24:21
如果您正在寻找一种使用Hashmap的方法,您可以这样做
public static void top5(int[] arr) {
LinkedHashMap<Integer, Integer> lookup = new LinkedHashMap<>();
for (int key : arr) {
if (lookup.containsKey(key)) {
lookup.put(key, lookup.get(key) + 1);
} else {
lookup.put(key, 1);
}
}
Map<Integer, Integer> result = lookup.entrySet() /* sorts the linked_map by value */
.stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
List<Integer> key_in_order
= new ArrayList<Integer>(result.keySet()); // convert to list
/* reverse the key because it was backward compared to what you want */
Collections.reverse(key_in_order);
for (int i = 0; i < 5; i++) {
System.out.println("key : "+String.valueOf(key_in_order.get(i)) + " value : " + result.get(key_in_order.get(i)) );
}
}对于java来说,结果需要非常大的函数lol --可能有一种更有效的方法--但这正是我个人想出来的
https://stackoverflow.com/questions/73756799
复制相似问题