Sort Elements by Frequency: 3 Approaches for Wipro Interviews
Sort elements of an array by frequency using HashMap sort, bucket sort, and TreeMap. Python and Java code examples, complexity table, and Wipro NTH context.
Sorting an array by element frequency shows up in Wipro NTH coding rounds because it tests hash-map counting and comparator logic in one question. The rule: order elements from most frequent to least, with ties broken by each element’s first appearance in the original array.
The Problem
Given an integer array, rearrange it so the most frequent element comes first, the next most frequent second, and so on. When two elements have the same count, the one that appeared at the earlier index in the input array comes first in the output.
Work through an example:
- Input:
[2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12] - Frequency count: 3 appears 4 times, 2 appears 3 times, 12 appears 2 times, 4 and 5 each appear once
- First-occurrence indices: 2 at index 0, 3 at index 1, 4 at index 3, 5 at index 4, 12 at index 5
- Output:
[3, 3, 3, 3, 2, 2, 2, 12, 12, 4, 5]
Why does 4 precede 5? Both appear once, but 4 is at index 3 and 5 is at index 4. Earlier first occurrence wins the tie.
Three approaches follow: HashMap with custom sort (simplest to explain), bucket sort (optimal time), and TreeMap grouping (cleaner Java idiom).
Approach 1: HashMap with Custom Sort
Count each element’s frequency with a dictionary, track its earliest index in one pass, then sort the unique elements by two criteria: descending frequency as the primary key, ascending first-occurrence index as the tiebreaker.
Python
Python’s collections.Counter builds the frequency map in one line. A tuple lambda key (-freq[u], first_seen[u]) sorts on both criteria at once: the negative sign flips frequency so that higher counts sort first, and the second element breaks ties by original position.
from collections import Counter
def sort_by_frequency(arr):
freq = Counter(arr)
first_seen = {}
for i, x in enumerate(arr):
if x not in first_seen:
first_seen[x] = i
unique = sorted(freq.keys(), key=lambda u: (-freq[u], first_seen[u]))
result = []
for u in unique:
result.extend([u] * freq[u])
return result
arr = [2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12]
print(sort_by_frequency(arr))
# Output: [3, 3, 3, 3, 2, 2, 2, 12, 12, 4, 5]
The first_seen dictionary fills in a single left-to-right pass: the if x not in first_seen guard ensures only the earliest index is stored, never overwritten by later occurrences of the same element.
Java
Java requires an explicit HashMap for frequencies and a second one for first-occurrence indices. The Comparator is defined inline in the sort call.
import java.util.*;
public class FrequencySort {
public static List<Integer> sortByFrequency(int[] arr) {
Map<Integer, Integer> freq = new HashMap<>();
Map<Integer, Integer> firstIdx = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
freq.merge(arr[i], 1, Integer::sum);
firstIdx.putIfAbsent(arr[i], i);
}
List<Integer> keys = new ArrayList<>(freq.keySet());
keys.sort((a, b) -> {
int diff = freq.get(b) - freq.get(a);
if (diff != 0) return diff;
return firstIdx.get(a) - firstIdx.get(b);
});
List<Integer> result = new ArrayList<>();
for (int k : keys)
for (int i = 0; i < freq.get(k); i++)
result.add(k);
return result;
}
}
merge(key, 1, Integer::sum) increments the count if the key exists, or inserts 1 on first encounter. putIfAbsent stores the index only when the element appears for the first time.
How it works
- Step 1: Single O(n) pass builds
freq(element to count) andfirst_seen(element to earliest index). - Step 2: Sort the unique elements with a custom key. Primary criterion: higher frequency sorts first. Secondary criterion for ties: lower first-seen index sorts first.
- Step 3: Expand each sorted unique element by repeating it
freq[element]times. Total output length equals input length, so this step is O(n).
Time: O(n log n). The sort dominates both O(n) passes. Space: O(n) for the two maps and the result array.
Approach 2: Bucket Sort
Bucket sort removes the comparison-based sort step by placing each element into a bucket indexed by its frequency. Frequencies can range from 1 to n (the full array length), so allocate n + 1 buckets, fill them in one pass, then read from buckets[n] down to buckets[1] to get descending order naturally.
from collections import Counter
def sort_by_frequency_bucket(arr):
freq = Counter(arr)
first_seen = {}
for i, x in enumerate(arr):
if x not in first_seen:
first_seen[x] = i
n = len(arr)
buckets = [[] for _ in range(n + 1)]
for x, f in freq.items():
buckets[f].append(x)
result = []
for f in range(n, 0, -1):
for x in sorted(buckets[f], key=lambda v: first_seen[v]):
result.extend([x] * f)
return result
Each buckets[f] holds all distinct elements that appear exactly f times. Iterating from high to low frequency handles the ordering without a sort call on the entire key list. Within a bucket, a sorted() call on the (usually small) group resolves tie-breaking by first-seen index.
Time: O(n) for building and scanning the n + 1 buckets. The inner sort adds O(k log k) per bucket where k is the number of distinct elements sharing that frequency; in practice k is small. Space: O(n).
Approach 3: TreeMap Grouping in Java
Java’s TreeMap with a reversed comparator groups elements by frequency automatically, eliminating the explicit flat-list sort. This separates the two concerns cleanly: the TreeMap handles frequency ordering, and a Comparator inside each group handles tie-breaking.
import java.util.*;
public class FrequencySortTreeMap {
public static List<Integer> sortByFrequency(int[] arr) {
Map<Integer, Integer> freq = new HashMap<>();
Map<Integer, Integer> firstIdx = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
freq.merge(arr[i], 1, Integer::sum);
firstIdx.putIfAbsent(arr[i], i);
}
TreeMap<Integer, List<Integer>> byFreq =
new TreeMap<>(Collections.reverseOrder());
for (Map.Entry<Integer, Integer> e : freq.entrySet()) {
byFreq.computeIfAbsent(e.getValue(), k -> new ArrayList<>())
.add(e.getKey());
}
List<Integer> result = new ArrayList<>();
for (Map.Entry<Integer, List<Integer>> e : byFreq.entrySet()) {
List<Integer> group = e.getValue();
group.sort(Comparator.comparingInt(firstIdx::get));
for (int el : group)
for (int i = 0; i < e.getKey(); i++)
result.add(el);
}
return result;
}
}
Collections.reverseOrder() keeps the TreeMap keys (frequencies) in descending order as elements are inserted. computeIfAbsent initialises the list for a new frequency key and returns the existing list for one already seen. The group-level Comparator.comparingInt(firstIdx::get) sorts ties by original position.
Time: O(n log n). Same asymptotic bound as Approach 1, though the constant factors differ slightly because TreeMap insertion is O(log n) rather than O(1). Space: O(n).
Complexity Comparison
| Approach | Time | Space | Best suited for |
|---|---|---|---|
| HashMap + custom sort | O(n log n) | O(n) | Interviews — easy to reason about verbally |
| Bucket sort | O(n) | O(n) | Large arrays with few distinct elements |
| TreeMap grouping (Java) | O(n log n) | O(n) | When grouping itself is useful downstream |
All three correctly implement the tie-breaking rule when the first_seen index map is included. The most common interview mistake is omitting first_seen and only sorting by frequency, which produces wrong output whenever two elements share a count. Always state the tie-breaking rule before writing the comparator so the interviewer sees you have the full specification in mind.
Wipro NTH and the AI Track
Frequency sort appears alongside other array manipulation problems in Wipro NTH coding rounds. The full topic list, test pattern, and eligibility criteria are in the Wipro NTH guide. Past-paper examples, including additional array and string problems that have repeated across drives, are in the Wipro placement papers collection.
The coding section of the NTH typically gives candidates two to three problems covering arrays, strings, and logical reasoning, with a time limit. Getting that section right matters more now than it did a few years ago. Wipro revised its FY26 fresher intake guidance from 10,000 to 12,000 down to 7,500 to 8,000, according to CHRO Saurabh Govil at the Q3 FY26 earnings call. Fewer seats, same candidate pool, so performance on each stage of the NTH (including the coding section) carries more weight than before.
At the same time, Wipro runs 50 university Centres of Excellence where it co-builds AI, cybersecurity, and data curricula with partner institutions. Candidates from those programs, or who demonstrate equivalent AI-readiness independently, are considered for a separate premium hiring track. For the Wipro interview questions that come after the coding screen, technical depth beyond the coding round is what separates standard offers from premium ones.
| Track | CTC | Entry path |
|---|---|---|
| Wipro Standard / Velocity | ₹3.5 to 4.0 LPA | NTH coding round, technical interview, HR round |
| Wipro CoE selected track | Premium (not publicly disclosed) | Campus CoE program or demonstrated AI skills |
The 2026 AI roadmap for Indian engineering students maps out what building that AI-readiness actually looks like across a placement timeline.
The HashMap counting pattern from Approach 1 (build a frequency map, then sort by its values) shows up again in LLM preprocessing: token frequency tables, vocabulary construction, and attention-pattern analysis all use the same structure. TinkerLLM is where you apply that pattern to real API calls rather than a contrived array. For ₹299, it puts a live Python environment and actual LLM endpoints in front of you from session one, so frequency-counting concepts move from interview whiteboard to deployed code.
Primary sources
Frequently asked questions
What does sort elements by frequency mean?
It means rearranging array elements so the most frequently occurring element appears first, the second most frequent next, and so on. Ties between equal-frequency elements are broken by whichever element appeared first in the original input array.
How do I sort an array by frequency in Python?
Use Counter from the collections module to build a frequency map in one line. Call sorted() on the unique elements with a tuple lambda key: (-frequency, first_seen_index). Then expand each unique element back to its full count using extend.
What is the time complexity of sort by frequency?
The HashMap plus custom sort approach is O(n log n) because the sort step dominates. Bucket sort brings the grouping step down to O(n), though tie-breaking within a frequency bucket still requires a nested sort in the worst case.
Does the sort by frequency problem appear in Wipro NTH?
Yes. Array manipulation problems including frequency sort appear in Wipro NTH coding rounds. The FACE Prep Wipro placement papers page lists more examples from past Wipro drives.
How do I handle ties in frequency sort?
When two elements share the same frequency, place the one with the lower first-occurrence index before the other. Track first occurrence with a dictionary keyed on each element, filled in a single left-to-right pass through the input array.
Which approach should I use in a Wipro interview?
Start with the HashMap plus sorted() approach because it is readable and has no hidden edge cases. Mention bucket sort as an O(n) optimisation if the interviewer asks how you would reduce time complexity for large inputs.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)