Top K Frequent Elements Medium

Problem Statement

  • Given an array with integers that can repeat, the aim is to return the top k most frequent elements from the array
  • Eg. Given array: [1, 1, 1, 3, 3, 2, 4, 5, 5, 6, 5, 7, 5] and k = 2. We have to find 2 most repeated elements, which is [5, 1] because 5 repeats 4 times and 1 repeats 3 times. 1 and 5 are the top 2 frequent elements.

Algorithm

  • Let us consider following array as an example
    Image

  • Here, 1 repeats 3 times, 2 repeats 2 times and 3 repeats 2 times. So the desired result is an array containing elements [ 1, 2, 3 ].
  • We have to write an algorithm to try and solve this in O(n) time and O(n) space.

Step 1

  • Firstly, we need to know the frequency of each element, for this, we create a HashMap, iterate through the given array and count the frequency of each element.
    Image

  • Here, the key of map is the element of the array and the value is the frequency of that element.

Step 2

  • Now, we need to create a frequency array of length = length of given array
    This frequency array will hold the elements with corresponding frequencies, eg, 1 will go in place 3 as it has a frequency of 3.
    Image

Step 3

  • Iterate through the frequency map and populate the frequency array.
    Image
  • Element 1 goes to position 3 as it has a frequency of 3.

    Image

  • Element 2 goes to position 2 as it has a frequency of 2.

    Image

  • Element 3 goes to position 2 since it has a frequency of 2.

    Image

  • Element 5 goes to position 1 since it has a frequency of 1.

Step 4

  • Now that we have populated the frequency array, we can iterate through the array from backwards until we find k elements (3 in our case) that are of high frequency.

    Image

  • No elements available for frequency 8.

    Image

  • No elements available for frequency 7.

    Image

  • No elements available for frequency 6.

    Image

  • No elements available for frequency 5.

    Image

  • No elements found for frequency 4.

    Image

  • Element 1 found at frequency 3 (Top frequency), We add it to the result array and proceed.

    Image

  • Element 2, 3 found at frequency 2, we add these to the result array.
    At this point, the result array has 3 elements (k = 3), we have top 3 frequent elements already, we can stop here and return the result.

    Image

Code

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        int[] result = new int[k];

        Map<Integer, Integer> map = Arrays.stream(nums)
            .boxed()
            .collect(
                Collectors.toMap(
                    e -> e,
                    e -> 1,
                    (key, dup) -> key + 1
                )
            );

        List<List<Integer>> frequencyBucket = IntStream.range(0, nums.length + 1)
            .boxed()
            .map(i -> new ArrayList<Integer>())
            .collect(Collectors.toList());
        

        map.forEach((num, freq) -> frequencyBucket.get(freq).add(num));

        System.out.println(frequencyBucket);

        int j = 0;
        for(int i = frequencyBucket.size() - 1; i > -1; i--) {
            List<Integer> freqElem = frequencyBucket.get(i);
            if (freqElem.size() == 0) continue;

            if (j == k) break;

            for (int l = 0; l < freqElem.size(); l++) {
                result[j] = freqElem.get(l);
                j++;
            }
        }

        return result;
    }
}