diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/frequentelements/MostFrequentElementsFinder.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/frequentelements/MostFrequentElementsFinder.java new file mode 100644 index 0000000000..ea127ea587 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/frequentelements/MostFrequentElementsFinder.java @@ -0,0 +1,103 @@ +package com.baeldung.algorithms.frequentelements; + +import java.util.*; +import java.util.stream.Collectors; + +public class MostFrequentElementsFinder { + + public static List findByHashMapAndPriorityQueue(Integer[] array, int n) { + Map countMap = new HashMap<>(); + + // For each element i in the array, add it to the countMap and increment its count. + for (Integer i : array) { + countMap.put(i, countMap.getOrDefault(i, 0) + 1); + } + + // Create a max heap (priority queue) that will prioritize elements with higher counts. + PriorityQueue heap = new PriorityQueue<>( + (a, b) -> countMap.get(b) - countMap.get(a)); + + // Add all the unique elements in the array to the heap. + heap.addAll(countMap.keySet()); + + List result = new ArrayList<>(); + for (int i = 0; i < n && !heap.isEmpty(); i++) { + // Poll the highest-count element from the heap and add it to the result list. + result.add(heap.poll()); + } + + return result; + } + + public static List findByStream(Integer[] arr, int n) { + // Create a Map to count occurrences of each element + Map countMap = Arrays.stream(arr) + .collect(Collectors.groupingBy(i -> i, Collectors.counting())); + + // Sort the elements by occurrence count + List sortedKeys = countMap.entrySet().stream() + .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + + // Extract the n most frequent elements from the sorted list + List result = new ArrayList<>(); + for (int i = 0; i < n && i < sortedKeys.size(); i++) { + result.add(sortedKeys.get(i)); + } + return result; + } + + public static List findByTreeMap(Integer[] arr, int n) { + // Create a TreeMap and use a reverse order comparator to sort the entries by frequency in descending order + Map countMap = new TreeMap<>(Collections.reverseOrder()); + + for (int i : arr) { + countMap.put(i, countMap.getOrDefault(i, 0) + 1); + } + + // Create a list of the map entries and sort them by value (i.e. by frequency) in descending order + List> sortedEntries = new ArrayList<>(countMap.entrySet()); + sortedEntries.sort((e1, e2) -> e2.getValue().compareTo(e1.getValue())); + + // Extract the n most frequent elements from the sorted list of entries + List result = new ArrayList<>(); + for (int i = 0; i < n && i < sortedEntries.size(); i++) { + result.add(sortedEntries.get(i).getKey()); + } + + return result; + } + + public static List findByBucketSort(Integer[] arr, int n) { + List result = new ArrayList<>(); + Map freqMap = new HashMap<>(); + List[] bucket = new List[arr.length + 1]; + + // Loop through the input array and update the frequency count of each element in the HashMap + for (int num : arr) { + freqMap.put(num, freqMap.getOrDefault(num, 0) + 1); + } + + // Loop through the HashMap and add each element to its corresponding bucket based on its frequency count + for (int num : freqMap.keySet()) { + int freq = freqMap.get(num); + if (bucket[freq] == null) { + bucket[freq] = new ArrayList<>(); + } + bucket[freq].add(num); + } + + // Loop through the bucket array in reverse order and add the elements to the result list + // until we have found the n most frequent elements + for (int i = bucket.length - 1; i >= 0 && result.size() < n; i--) { + if (bucket[i] != null) { + result.addAll(bucket[i]); + } + } + + // Return a sublist of the result list containing only the first n elements + return result.subList(0, n); + } + +} diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/frequentelements/MostFrequentElementsUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/frequentelements/MostFrequentElementsUnitTest.java new file mode 100644 index 0000000000..9fa4862163 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/frequentelements/MostFrequentElementsUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.algorithms.frequentelements; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +public class MostFrequentElementsUnitTest { + + private final Integer[] inputArray = {1, 2, 3, 4, 5, 5, 5, 6, 6, 7, 7, 7, 7, 8, 9, 9, 9, 9, 9}; + private final int n = 3; + private final Integer[] outputArray = {9, 7, 5}; + + @Test + void givenIntegersArray_UseFindByHashMapAndPriorityQueueMethod_thenReturnMostFrequentElements() { + assertThat(MostFrequentElementsFinder.findByHashMapAndPriorityQueue(inputArray, n)).containsExactly(outputArray); + } + + @Test + void givenIntegersArray_UseFindByBucketSortMethod_thenReturnMostFrequentElements() { + assertThat(MostFrequentElementsFinder.findByBucketSort(inputArray, n)).containsExactly(outputArray); + } + + @Test + void givenIntegersArray_UseFindByStreamMethod_thenReturnMostFrequentElements() { + assertThat(MostFrequentElementsFinder.findByStream(inputArray, n)).containsExactly(outputArray); + } + + @Test + void givenIntegersArray_UseFindByTreeMapMethod_thenReturnMostFrequentElements() { + assertThat(MostFrequentElementsFinder.findByTreeMap(inputArray, n)).containsExactly(outputArray); + } + +}