Top K Frequent Elements in Java DSA: HashMap, Heap, and Bucket Sort

  • Last Updated: August 8, 2026
  • By: javahandson
  • Series
img

Top K Frequent Elements in Java DSA: HashMap, Heap, and Bucket Sort

Solve Top K Frequent Elements in Java DSA three ways — HashMap sort, min-heap, and O(n) bucket sort — with beginner-friendly dry runs and clean code.

1. Introduction

Top K Frequent Elements in Java is a problem that shows up a lot in interviews. It sounds fancy, but the idea is plain. You are given a list of numbers, and you must return the k numbers that appear most often.

Say the list is [1, 1, 1, 2, 2, 3, 4] and k is 2. The number 1 shows up three times, and 2 shows up twice. So the answer is [1, 2], because those two are the most frequent.

The order of the answer does not matter here. As long as you return the correct k numbers, you are good.

We build the solution in three steps, like always. Counting with a HashMap and then sorting is the first, easy idea. A heap of size k is the next step up. The bucket sort trick is the lean version that runs in linear time and wins interviews.

Every approach gets a full, step-by-step dry run on the same list. Nothing gets skipped, so you can watch the counts grow and see exactly why each number lands in the answer.

2. Understanding the Problem

Let us pin down the rules before writing any code.

  • You get an array of numbers, for example nums = [1, 1, 1, 2, 2, 3, 4].
  • You also get a number k, which tells you how many top elements to return.
  • Return the k numbers that appear most often in the array.
  • The answer can be in any order, so [1, 2] and [2, 1] are both accepted.

For our example the answer is [1, 2]. The value 1 appears three times, which is the highest count. Next comes 2 with a count of two. The numbers 3 and 4 appear only once each, so they miss the cut.

The problem also promises the answer is always unique. That means you will never face a tie that makes the top k unclear.

3. Concepts You Need Here

3.1 Frequency Counting With a HashMap

Every approach starts the same way. You walk the array once and count how many times each number appears. A HashMap is perfect for this job.

  • The key is the number, and the value is its count.
  • Each time you see a number, you add one to its count.

After one pass you know the exact frequency of every number. That map is the base for all three approaches.

3.2 Picking the Top k Counts

Once you have the counts, the real question is how to pull out the k largest. There are three common ways, and they differ in speed.

  • Sorting all counts is the simplest, but it does more work than needed.
  • A heap of size k keeps only the best candidates, so it is faster.
  • Bucket sort groups numbers by their exact count, which reaches linear time.

4. Approach 1: Count, Then Sort by Frequency

First count every number with a HashMap. Then take the map entries and sort them by count, from highest to lowest. Finally, pick the first k numbers from that sorted list. It is the most direct idea, even though sorting is more work than the problem truly needs.

4.1 Pseudocode

count = empty map from number to its count
 
for num in nums:
    count[num] = count[num] + 1
 
entries = list of (number, count) pairs from count
sort entries by count from high to low
 
result = first k numbers from entries
return result

4.2 Pseudocode Explained

The plan reads top to bottom in three plain moves: count first, sort next, then slice off the top k. Let us look at each line and see what it does and why.

The counting loop.

  • The line count[num] = count[num] + 1 runs once for every number in the array.
  • Each time we meet a number, we add one to its running total. So a number seen three times ends with a count of 3.
  • After this loop finishes, the map holds every distinct number paired with how often it showed up. That is the only pass we make over the raw array.

Turning the map into a sortable list.

  • A map has no fixed order, and you cannot sort it directly. So we copy its entries into a plain list of pairs.
  • Each pair is one number together with its count, which is exactly what we will sort on.

Sorting by count, high to low.

  • We sort the list so the pair with the biggest count comes first. This is the key step, because the most frequent numbers now sit at the front.
  • Notice we sort by the count, not by the number itself. The number 5 with count 9 should beat the number 100 with count 2.

Slicing the answer.

  • Once the list is sorted, the top k numbers are simply the first k entries.
  • We copy just their numbers into the result and hand it back. The counts have done their job and are no longer needed.

4.3 Java Code

import java.util.*;
 
public class TopKSort {
 
    public static int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> count = new HashMap<>();
        for (int num : nums) {
            count.put(num, count.getOrDefault(num, 0) + 1);
        }
 
        List<Integer> keys = new ArrayList<>(count.keySet());
        keys.sort((a, b) -> count.get(b) - count.get(a));
 
        int[] result = new int[k];
        for (int i = 0; i < k; i++) {
            result[i] = keys.get(i);
        }
        return result;
    }
 
    public static void main(String[] args) {
        int[] nums = {1, 1, 1, 2, 2, 3, 4};
        System.out.println(Arrays.toString(topKFrequent(nums, 2))); // [1, 2]
    }
}

4.4 Java Code Explained

This is the same plan written in Java. The one helper to know is getOrDefault, which returns 0 for a number we have not seen yet, so we never hit a null.

  • Lines 6 to 9 build the count map. For each number, getOrDefault gives its current count, and we add one.
  • Then line 11 copies all the distinct numbers into a list, since a map itself is not sorted.
  • Line 12 sorts that list. The comparator count.get(b) – count.get(a) puts the higher count first.
  • Lines 14 to 17 read the first k numbers from the sorted list into the answer array.

4.5 Dry Run of the Sort Approach

Let us trace nums = [1, 1, 1, 2, 2, 3, 4] with k = 2. First we build the count map in one pass. The table shows the map after reading each number.

i (read index) num map after this step
0 1 {1:1}
1 1 {1:2}
2 1 {1:3}
3 2 {1:3, 2:1}
4 2 {1:3, 2:2}
5 3 {1:3, 2:2, 3:1}
6 4 {1:3, 2:2, 3:1, 4:1}

Now we take the distinct numbers [1, 2, 3, 4] and sort them by count from high to low. The next table shows the order settling as the comparator compares counts.

number its count position after sort
1 3 1st (highest count)
2 2 2nd
3 1 3rd
4 1 4th

The sorted list of numbers is [1, 2, 3, 4]. We take the first k = 2 of them, which gives the answer [1, 2].

4.6 Reading the Dry Run

Let us walk the trace in two parts and see what each part buys us.

The counting pass over nums.

This pass just tallies how often each number appears. The map starts empty and grows one entry at a time as we read left to right. Read the last table column as a photo of the map right after each number is processed.

  • At i=0 we read the number 1. It is not in the map yet, so it enters fresh with a count of 1. The map is now {1:1}.
  • Moving to i=1 we read 1 again. It already sits at count 1, so we add one and it becomes 2. The map is {1:2}.
  • Reading i=2 gives 1 a third time, so its count climbs from 2 to 3. The map is {1:3}, and 1 is now clearly the front-runner.
  • At i=3 the number 2 arrives, and it is brand new. So it enters the map with a count of 1, giving {1:3, 2:1}.
  • Then i=4 reads 2 once more, bumping its count from 1 to 2. The map is now {1:3, 2:2}.
  • During i=5 the number 3 shows up for the first time, so it joins at count 1. The map grows to {1:3, 2:2, 3:1}.
  • Finally i=6 reads 4, also new, so it enters at count 1. The map ends as {1:3, 2:2, 3:1, 4:1}.

After the whole pass the map reads {1:3, 2:2, 3:1, 4:1}. That is the frequency fingerprint of the array: 1 appeared three times, 2 twice, and both 3 and 4 once each. Every later step in every approach builds on top of this same map.

The sorting pass over the counts.

Now we take the four distinct numbers and sort them by their count, largest first. The one thing to hold in your head: the sort compares counts, never the numbers themselves. A big number with a small count still loses.

  • The number 1 has count 3, which is the biggest of all four. So it wins every comparison and lands at the very front of the sorted list.
  • Next comes 2 with count 2. It beats both 3 and 4, whose counts are only 1, so it settles into second place.
  • Both 3 and 4 sit at count 1, a tie. Since the problem promises a unique answer, this tie never reaches into our top k, so their order between themselves does not matter.

The sorted list of numbers is [1, 2, 3, 4]. We slice off the first k = 2 entries, which are 1 and 2, and return them. Sorting worked, but look closely: we ordered all four numbers just to keep the top two. Half that work was wasted. That wasted effort is exactly what the heap and bucket approaches trim away.

💡 Interview Insight
A common opener is “what is the time cost of this approach?” Say O(n log n), because sorting the counts dominates. That answer sets you up to say you can do better.

4.7 Time and Space Cost

  • Time is O(n log n), because sorting the distinct counts dominates the work.
  • Space is O(n), for the map and the list of numbers we build.

Sorting is clean and short, but that log n factor is wasted effort. We only wanted the top k, not a fully ordered list. So next we keep just the best k with a heap.

5. Approach 2: Keep Top k With a Min-Heap

Count every number first, same as before. Then push each (count, number) pair into a min-heap, but never let the heap grow past size k. Whenever it holds more than k pairs, pop the smallest count out. After all pairs go through, the heap holds exactly the k most frequent numbers. This skips sorting the whole thing.

5.1 Pseudocode

count = empty map from number to its count
 
for num in nums:
    count[num] = count[num] + 1
 
heap = empty min-heap ordered by count
 
for (number, cnt) in count:
    push (cnt, number) into heap
    if size of heap > k:
        pop the smallest from heap
 
result = every number left in heap
return result

5.2 Pseudocode Explained

First, a quick word on what a min-heap is, because the whole approach rests on it. A min-heap is a collection that always keeps its smallest item on top and ready to remove. Here we order by count, so the number with the lowest count is always the one sitting on top. Picture a small box that holds only k pairs at a time.

Pushing a pair.

  • For each number and its count, we push the pair into the heap. The heap quietly rearranges itself so the smallest count floats to the top.
  • We do this for every distinct number, one at a time. We never look at the raw array again, only at the counts.

Guarding the size.

  • Right after each push we check: is the heap bigger than k? If yes, we run pop the smallest, which removes the top pair.
  • The top pair is always the one with the lowest count in the heap, so popping it throws away the weakest candidate we have seen so far.
  • This keeps the heap at exactly k pairs. It can briefly hold k+1 right after a push, but the pop brings it straight back to k.

Collecting the answer.

  • Once every number has passed through, only the k strongest survive inside the heap.
  • We read out their numbers and return them. Any pair with a low count was already popped and forgotten along the way.

5.3 Java Code

import java.util.*;
 
public class TopKHeap {
 
    public static int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> count = new HashMap<>();
        for (int num : nums) {
            count.put(num, count.getOrDefault(num, 0) + 1);
        }
 
        // min-heap ordered by count (smallest count on top)
        PriorityQueue<int[]> heap =
            new PriorityQueue<>((a, b) -> a[1] - b[1]);
 
        for (Map.Entry<Integer, Integer> e : count.entrySet()) {
            heap.offer(new int[]{e.getKey(), e.getValue()});
            if (heap.size() > k) {
                heap.poll();
            }
        }
 
        int[] result = new int[k];
        for (int i = 0; i < k; i++) {
            result[i] = heap.poll()[0];
        }
        return result;
    }
 
    public static void main(String[] args) {
        int[] nums = {1, 1, 1, 2, 2, 3, 4};
        System.out.println(Arrays.toString(topKFrequent(nums, 2))); // [1, 2] in some order
    }
}

5.4 Java Code Explained

The Java version uses a PriorityQueue, which is Java’s built-in heap. Each item is a small int array where slot 0 is the number and slot 1 is its count.

  • Lines 6 to 9 build the count map, exactly like the first approach.
  • Lines 12 and 13 create the min-heap. The comparator a[1] – b[1] orders pairs by count, so the smallest count sits on top.
  • Then lines 15 to 20 push each pair in, and pop the top whenever the size passes k.
  • Lines 22 to 26 drain the heap into the answer array, since whatever is left is the top k.

5.5 Dry Run of the Heap Approach

We reuse the same map {1:3, 2:2, 3:1, 4:1} and k = 2. We walk its entries in the order 1, 2, 3, 4 to keep the trace clear. The heap keeps its smallest count on top, ready to be popped.

step pair pushed (num, cnt) size > k? action heap after step (num:cnt)
1 (1, 3) no (size 1) push only 1:3
2 (2, 2) no (size 2) push only 2:2, 1:3
3 (3, 1) yes (size 3) push, then pop top 3:1 2:2, 1:3
4 (4, 1) yes (size 3) push, then pop top 4:1 2:2, 1:3

After every pair is processed, the heap holds 2:2 and 1:3. We drain it into the answer, giving [2, 1]. The order differs from the sort approach, but both numbers are correct.

5.6 Reading the Dry Run

Let us go step by step and watch the small heap fill up and then guard its own size. Keep k = 2 in mind: the heap is never allowed to hold more than two pairs for long. Remember the rule of a min-heap, the smallest count is always on top, first in line to be removed.

First step, push (1, 3).

The heap starts empty, so the pair 1:3 goes straight in with no fuss. It now holds one pair, which is not over k, so nothing gets popped. Right now the top is 1:3, because it is the only pair there.

Next step, push (2, 2).

Now the pair 2:2 enters. The heap compares counts and sees that 2 is smaller than 3.

  • Because a min-heap keeps the smallest count on top, the pair 2:2 rises above 1:3.
  • The heap now holds two pairs, which is exactly k. Two is not over the limit, so no pop happens yet.
  • At this moment the heap is 2:2 on top, then 1:3 below.

Third step, push (3, 1), then pop.

The pair 3:1 goes in. Its count of 1 is the smallest so far, so it floats to the very top. Now the heap holds three pairs, which is over k, so the guard fires and we pop the top.

  • The top is 3:1, since count 1 is the smallest in the heap right now.
  • Popping it removes 3, the least frequent number we have met so far. That is precisely the number we do not want in a top-two answer.
  • What remains is 2:2 and 1:3, the two strongest candidates, and the size is back to k.

Last step, push (4, 1), then pop.

The final pair 4:1 enters. Just like 3:1 before it, its count of 1 is the smallest, so it lands on top. The size is 3 again, over k, so we pop once more.

  • This time the top is 4:1, tied at count 1 and sitting right there ready to go.
  • Popping it drops 4, so the heap returns to size 2.
  • The survivors are still 2:2 and 1:3, which become our final top two.

Look at what happened across the whole run: we never sorted all four numbers. The heap held at most k+1 pairs at any instant, and it quietly threw away the weak ones the moment they made it too big. Each push or pop only shuffles a heap of size k, which is cheap. That is why the heap beats a full sort when k is small.

💡 Interview Insight
If asked “why a min-heap and not a max-heap?” explain that a min-heap of size k keeps the smallest count on top, so the weakest candidate is always the one you pop. That is exactly the one you want to drop.

5.7 Time and Space Cost

  • Time is O(n log k), since each push or pop costs log k and we do it for every distinct number.
  • Space is O(n + k), for the count map and the heap of size k.

This beats the full sort when k is much smaller than the number of distinct values. Still, there is one more trick that drops the time all the way to linear.

6. Approach 3: Bucket Sort by Frequency

Here is the clever part. A number in an array of size n can appear at most n times. So we make n+1 buckets, one for each possible count from 0 to n. We drop each number into the bucket that matches its count. Then we scan buckets from the highest count downward and collect numbers until we have k. No sorting, no heap, just plain array indexing. This is the answer interviewers hope to see.

6.1 Pseudocode

count = empty map from number to its count
 
for num in nums:
    count[num] = count[num] + 1
 
buckets = array of (n + 1) empty lists   // index = frequency
 
for (number, cnt) in count:
    add number to buckets[cnt]
 
result = empty list
for freq from n down to 1:
    for number in buckets[freq]:
        add number to result
        if size of result == k:
            return result

6.2 Pseudocode Explained

The whole trick is one idea: use the count itself as an array index. Bucket number 3 holds every number that appeared exactly three times. Bucket number 1 holds every number that appeared once. Because a number can show up at most n times in an array of size n, we make n+1 buckets, one for each count from 0 to n.

Counting, then building empty buckets.

  • We count every number first, exactly like the other two approaches.
  • Then we create an array of n + 1 empty lists. The list at index f will collect all numbers whose count is f.

Filling the buckets.

  • For each number and its count, we drop the number into the bucket at that count. A number with count 3 goes into bucket 3, and so on.
  • Notice there is no comparing here. We jump straight to the right bucket using the count as the index, which is why this step is so fast.

Scanning from the top down.

  • Now we walk the buckets from the highest index down toward 1. The highest indexes hold the most frequent numbers, so they come out first.
  • Empty buckets are skipped instantly. We only stop to collect from buckets that actually hold numbers.
  • The moment we have gathered k numbers, we stop and return. We never look at the lower buckets, because we already have our answer.

6.3 Java Code

import java.util.*;
 
public class TopKBucket {
 
    public static int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> count = new HashMap<>();
        for (int num : nums) {
            count.put(num, count.getOrDefault(num, 0) + 1);
        }
 
        // index = frequency, value = numbers with that frequency
        List<Integer>[] buckets = new List[nums.length + 1];
        for (Map.Entry<Integer, Integer> e : count.entrySet()) {
            int freq = e.getValue();
            if (buckets[freq] == null) {
                buckets[freq] = new ArrayList<>();
            }
            buckets[freq].add(e.getKey());
        }
 
        int[] result = new int[k];
        int idx = 0;
        for (int freq = nums.length; freq >= 1 && idx < k; freq--) {
            if (buckets[freq] != null) {
                for (int num : buckets[freq]) {
                    result[idx++] = num;
                    if (idx == k) {
                        break;
                    }
                }
            }
        }
        return result;
    }
 
    public static void main(String[] args) {
        int[] nums = {1, 1, 1, 2, 2, 3, 4};
        System.out.println(Arrays.toString(topKFrequent(nums, 2))); // [1, 2]
    }
}

6.4 Java Code Explained

The code looks long, but each part is simple. The buckets array does the heavy lifting, and the count value becomes the array index.

  • Lines 6 to 9 build the count map, the same first step as before.
  • Line 12 makes an array of lists sized nums.length + 1, so every possible count from 0 to n has a slot.
  • Then lines 13 to 19 read each number and drop it into the bucket for its count, creating the list if it is empty.
  • Lines 23 to 32 scan from the highest count down, pulling numbers into the answer until we have k, then stopping.

6.5 Dry Run of the Bucket Sort

Same input, nums = [1, 1, 1, 2, 2, 3, 4], k = 2, and the count map {1:3, 2:2, 3:1, 4:1}. The array length is 7, so we make 8 buckets, indexed 0 through 7. First we fill the buckets by walking the map entries in the order 1, 2, 3, 4.

step num its count bucket updated buckets so far (index:list)
1 1 3 buckets[3].add(1) 3:[1]
2 2 2 buckets[2].add(2) 2:[2], 3:[1]
3 3 1 buckets[1].add(3) 1:[3], 2:[2], 3:[1]
4 4 1 buckets[1].add(4) 1:[3,4], 2:[2], 3:[1]

Now we scan the buckets from index 7 down to 1 and collect numbers until we hold k = 2. Empty buckets are skipped.

freq (bucket index) bucket contents action result after step
7 empty skip []
6 empty skip []
5 empty skip []
4 empty skip []
3 [1] take 1 [1]
2 [2] take 2 (now size 2 = k) [1, 2]

We reached k numbers at frequency 2, so we stop right there. The answer is [1, 2], and we never even looked at bucket 1.

6.6 Reading the Dry Run

Let us walk the two phases and see why plain array indexing beats sorting here. Recall the setup: the array length is 7, so we have 8 buckets numbered 0 through 7, and the index of a bucket is the frequency it stores.

The bucket-fill phase.

Each number drops into the bucket that matches its count. The count is used directly as the index, so there are no comparisons at all, just a jump to the right slot.

  • At step 1 we take the number 1, whose count is 3. So we drop it into bucket 3. Now bucket 3 holds [1].
  • Next, step 2 takes 2, whose count is 2, so it goes into bucket 2. Bucket 2 now holds [2].
  • During step 3 we take 3, whose count is 1, so it joins bucket 1. Bucket 1 holds [3].
  • Then step 4 takes 4, whose count is also 1. It joins the same bucket 1, which now holds both [3, 4].

After filling, three buckets have numbers: bucket 3 holds [1], bucket 2 holds [2], and bucket 1 holds [3, 4]. The higher buckets 4, 5, 6, and 7 stay empty, because no number in our array appeared that many times. Those empty buckets are fine, we will just skip over them.

The scan phase, high to low.

Now we read buckets from the top index downward. Because higher indexes mean higher frequency, the most frequent numbers come out first. We collect numbers into the result and stop the very moment we have k of them.

  • We start at bucket 7 and move down through 6, 5, and 4. All four are empty, so we skip past each one without collecting anything.
  • At bucket 3 we find [1], so we take 1 into the result. The result is now [1], which has size 1, still short of k.
  • Dropping to bucket 2 we find [2], so we take 2. The result becomes [1, 2], which has size 2, and 2 equals k.

Since the result now holds k = 2 numbers, we stop immediately. We never even touched bucket 1, so the numbers 3 and 4 were never considered for the answer. Count each phase once: one pass to count, one pass to fill buckets, and at most one pass to scan. No phase ever sorts, so nothing costs log n. That early stop, plus zero sorting, is why bucket sort runs in linear time.

💡 Interview Insight
Interviewers love to ask “how is this O(n) when the last approaches were slower?” The reason is simple: counting is one pass, filling buckets is one pass, and scanning buckets is at most one more pass. No step ever sorts, so nothing costs log n.

6.7 Comparing the Three Traces

Approach How it picks top k Extra memory Speed feel
Count then sort Sort all counts, slice k Map plus list of numbers Slowest of the three
Min-heap of size k Keep only best k, pop rest Map plus heap of size k Fast, log k per number
Bucket sort Index by count, scan top down Map plus n+1 buckets Fastest, linear time

7. Comparing the Three Approaches

All three return the correct top k numbers. They just pay different prices to get there.

Approach Time Space Note
Count then sort O(n log n) O(n) Simple, but sorts more than needed
Min-heap of size k O(n log k) O(n + k) Great when k is small
Bucket sort O(n) O(n) Fastest, the expected answer

The heap wins over the full sort when k is small, because log k is smaller than log n. But bucket sort skips comparisons entirely, so it reaches linear time.

In an interview, mention the sort first to show you understand the problem. Then bring up the heap as a faster option for small k. Finally, land on bucket sort as the linear-time answer. That progression tells a clean story.

💡 Interview Insight
If pushed on why bucket sort is O(n) space and not less, point out the n+1 buckets. The buckets array grows with the input size, so it counts as linear extra space, even though the scan itself is quick.

8. Common Mistakes and Edge Cases

A few small traps catch beginners on Top K Frequent Elements. Keep them in mind.

  • Forgetting that the answer order does not matter, and wasting time forcing a specific order.
  • Sizing the buckets array wrong. It must be n + 1, because a number can appear up to n times.
  • Using a max-heap of every element instead of a min-heap of size k, which uses more memory than needed.
  • Assuming the input has no duplicates, when duplicates are the whole point of the problem.
  • When k equals the number of distinct values, you simply return them all.

Run a case where k equals the distinct count, and a case with a single repeated number, before you call your code done. These catch more bugs than any ordinary input will.

9. Interview Questions

Q: What is the most efficient way to solve Top K Frequent Elements in Java?

A: Bucket sort is the fastest, running in O(n) time. You count each number with a HashMap, drop each number into a bucket indexed by its frequency, then scan buckets from the highest count down until you collect k numbers. No sorting or heap is needed.

Q: Why use a min-heap instead of a max-heap for Top K Frequent Elements?

A: A min-heap of size k keeps the smallest count on top, so the weakest candidate is always the one you pop when the heap grows past k. This keeps only the k strongest numbers and costs O(n log k), which beats sorting everything when k is small.

Q: What size should the buckets array be in the bucket sort approach?

A: The buckets array must have n + 1 slots, where n is the array length. A number can appear at most n times, so you need a bucket for every possible frequency from 0 to n. Sizing it smaller will cause an index error for the most frequent element.

Q: Does the order of the output matter for Top K Frequent Elements?

A: No. Any order is accepted, so [1, 2] and [2, 1] are both correct answers. That is why the heap approach can return the numbers in a different order than the sort approach while still being right.

Q: What is the time complexity of each Top K Frequent Elements approach?

A: Count then sort is O(n log n). The min-heap of size k is O(n log k). Bucket sort is O(n), which is the best of the three, because counting, filling buckets, and scanning are each a single pass with no comparisons.

10. Conclusion

Top K Frequent Elements in Java looks tricky at first, yet it rests on one habit you will reuse everywhere: count first, then decide how to pick the top. Once you see the array as a bag of counts, the whole problem clicks.

Our seven-number trace showed the payoff clearly. Sorting ordered every count just to keep two. The heap kept only the best k and threw the rest away. Bucket sort used the count as an index and scanned from the top, reaching linear time.

So take the pattern, not just the answer. When you need the largest k of something, a heap of size k or a bucket by value will usually beat a full sort. Reach for buckets when the values fit a small range, and keep the heap handy when k is small.

That counting habit turns many array and hashing problems from tricky into routine. It will serve you well on the harder problems waiting further down the list.

11. Further Reading

 

Leave a Comment