Skip to main content

Group By - Solution & Explanation

Medium10 min read
Practice this problem

Problem Statement

Write code that enhances all arrays such that you can call the array.groupBy(fn) method on any array and it will return a grouped version of the array.

A grouped array is an object where each key is the output of fn(arr[i]) and each value is an array containing all items in the original array which generate that key.

The provided callback fn will accept an item in the array and return a string key.

The order of each value list should be the order the items appear in the array. Any order of keys is acceptable.

Please solve it without lodash's _.groupBy function.

 

Example 1:

Input: 
array = [
  {"id":"1"},
  {"id":"1"},
  {"id":"2"}
], 
fn = function (item) { 
  return item.id; 
}
Output: 
{ 
  "1": [{"id": "1"}, {"id": "1"}],   
  "2": [{"id": "2"}] 
}
Explanation:
Output is from array.groupBy(fn).
The selector function gets the "id" out of each item in the array.
There are two objects with an "id" of 1. Both of those objects are put in the first array.
There is one object with an "id" of 2. That object is put in the second array.

Example 2:

Input: 
array = [
  [1, 2, 3],
  [1, 3, 5],
  [1, 5, 9]
]
fn = function (list) { 
  return String(list[0]); 
}
Output: 
{ 
  "1": [[1, 2, 3], [1, 3, 5], [1, 5, 9]] 
}
Explanation:
The array can be of any type. In this case, the selector function defines the key as being the first element in the array. 
All the arrays have 1 as their first element so they are grouped together.
{
  "1": [[1, 2, 3], [1, 3, 5], [1, 5, 9]]
}

Example 3:

Input: 
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
fn = function (n) { 
  return String(n > 5);
}
Output:
{
  "true": [6, 7, 8, 9, 10],
  "false": [1, 2, 3, 4, 5]
}
Explanation:
The selector function splits the array by whether each number is greater than 5.

 

Constraints:

  • 0 <= array.length <= 105
  • fn returns a string

Approach Overview

Problem Overview: You receive an array and a function fn. For every element in the array, the function returns a key. The task is to group elements that produce the same key and return them in a structure where each key maps to the list of corresponding elements.

Approach 1: Iterative Grouping (Hash Map) (Time: O(n), Space: O(n))

The straightforward approach iterates through the array once and builds groups using a hash map (or dictionary/object depending on the language). For each element x, compute the key using fn(x). Check whether that key already exists in the map. If it does, append the element to the existing list; otherwise create a new list and insert the element. This works because hash map lookups and insertions are constant time on average. After processing all elements, the map directly represents the grouped result. This approach is widely used in real systems for aggregation tasks such as categorizing logs or grouping records by attribute. It relies heavily on fast key lookups provided by a hash map and sequential traversal of the array.

Approach 2: Recursive Grouping with Memoization (Time: O(n), Space: O(n))

A recursive variant processes the array one index at a time while maintaining a shared memo structure that stores grouped results. The recursion processes element i, computes fn(arr[i]), inserts the value into the corresponding group, and then calls itself for i + 1. Memoization simply means the grouping map persists across recursive calls rather than being rebuilt. This produces the same final structure as the iterative solution but expresses the traversal through recursion. The recursion depth becomes n, which adds stack usage, making it slightly less practical in languages with strict recursion limits. This approach mainly demonstrates recursive problem decomposition and ties into concepts from recursion.

Recommended for interviews: The iterative hash map approach is what interviewers typically expect. It shows you recognize grouping as a hash map aggregation problem and can implement it in a single pass with O(n) time. Mentioning the recursive alternative demonstrates deeper understanding of traversal strategies, but the iterative method is clearer, safer for large inputs, and closer to production code.

Approach 1: Iterative Grouping

This approach involves iterating over each element of the array, applying the provided function to determine the key for each element, and then organizing elements in an object based on these keys.

This solution represents the grouping result using a list of structures in C. Each structure holds a key and a dynamically sized array of values. The code iterates through the input array, applies the function to get keys, and organizes them accordingly.

Code

C

C++

Java

Python

C#

JavaScript

Complexity

Time Complexity: O(n * m) where n is the number of elements and m is the average length of strings (due to strcmp operation).
Space Complexity: O(n) for storage of key-value mappings.

Try this approach in the editor →

Approach 2: Recursive Grouping with Memoization

This approach recursively divides the array, processes elements with memoization to store previously encountered keys, thus reducing redundant calculations, which optimizes processing of large arrays.

In this recursive implementation, the function would conceptually keep a cache of already encountered keys, to avoid recalculating them. As memory allocation and proper recursive function configuration is complex in C, it's a theoretical implementation.

Code

C

C++

Java

Python

C#

JavaScript

Complexity

Time Complexity: O(n * m), where m is affected by recursion depth.
Space Complexity: O(n) for memo storage and call stack.

Try this approach in the editor →

Approach 3: Default Approach

Code

TypeScript

Try this approach in the editor →

Complexity Comparison

ApproachComplexity
Iterative Grouping

Time Complexity: O(n * m) where n is the number of elements and m is the average length of strings (due to strcmp operation).
Space Complexity: O(n) for storage of key-value mappings.

Recursive Grouping with Memoization

Time Complexity: O(n * m), where m is affected by recursion depth.
Space Complexity: O(n) for memo storage and call stack.

Default Approach—

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Iterative Grouping (Hash Map)O(n)O(n)Best general solution. Efficient single-pass grouping using constant-time hash lookups.
Recursive Grouping with MemoizationO(n)O(n) + recursion stackUseful for demonstrating recursion-based traversal or functional-style implementations.

Video Solution

Group By - Leetcode 2631 - JavaScript 30-Day Challenge • NeetCodeIO • 5,354 views views

Watch 7 more video solutions →

Frequently Asked Questions

Is Group By easy or hard?
The problem is typically rated Medium because it tests understanding of hash map grouping patterns rather than complex algorithms. The logic is straightforward, but recognizing the aggregation pattern quickly is the key skill being evaluated.
Group By Python/Java solution
In Python, a dictionary maps keys to lists and elements are appended using dict.setdefault or defaultdict. In Java, a HashMap maps keys to ArrayLists with computeIfAbsent used to initialize groups. Both implementations follow the same O(n) hash-based grouping strategy.
How to solve Group By in O(n)?
Traverse the array once and maintain a hash map where the key is the result of the grouping function. For each element, compute the key, check if the key exists in the map, and append the value to the corresponding array. This single-pass aggregation ensures O(n) time complexity.
What is the best approach for Group By?
The optimal approach uses a hash map to group elements in a single pass. Iterate through the array, compute a key using the provided function, and append the element to the corresponding list in the map. This runs in O(n) time with O(n) space and is the standard solution expected in interviews.
Is Group By asked at Google/Amazon/Meta?
Grouping problems appear frequently in interviews at large tech companies because they test understanding of hash maps and data aggregation patterns. Variants show up in questions involving log analysis, categorization, and frequency grouping.
What data structure is used in Group By?
A hash map (dictionary or object) is the core data structure. It maps each computed key to a list of elements that share that key. The hash map enables constant-time insertion and lookup, which keeps the overall algorithm linear.
What is the time complexity of Group By?
The optimal solution runs in O(n) time because each element is processed exactly once and hash map operations are O(1) on average. Space complexity is O(n) since every element must appear in a grouped list in the output structure.

Ready to solve this problem?

Practice Group By with our built-in code editor and test cases.

Practice on FleetCode