BackmediumStrings

Categorical Array Segmentation Solution

Problem Statement

You are provided with an array of strings, where each string consists solely of lowercase English letters. Your objective is to partition these strings into distinct clusters based on their character frequency profiles. Two strings are considered equivalent and must be placed in the same cluster if and only if they are anagrams of each other. This means that for any two strings in the same cluster, the count of every character from 'a' to 'z' must be identical, regardless of the order in which the characters appear within the string.

The grouping logic relies on the multiset of characters contained in each string. If string A contains two 'a's, one 'b', and no other characters, and string B also contains two 'a's, one 'b', and no other characters, they belong to the same group, even if A is "aab" and B is "aba". Conversely, if the frequency of any single character differs between two strings, they must reside in separate groups.

Return a list of lists, where each inner list contains all strings from the input array that share the same character composition. The order of the groups in the returned list does not matter, nor does the order of strings within each group. However, every string from the input must appear exactly once in the output.

Example 1
Input
words = ["listen", "silent", "hello", "olleh", "world"]
Output
[["listen", "silent"], ["hello", "olleh"], ["world"]]

Explanation: 1. Analyze "listen": character counts are {l:1, i:1, s:1, t:1, e:1, n:1}. 2. Analyze "silent": character counts are {s:1, i:1, l:1, e:1, n:1, t:1}. This matches "listen", so they form a group. 3. Analyze "hello": character counts are {h:1, e:1, l:2, o:1}. 4. Analyze "olleh": character counts are {o:1, l:2, e:1, h:1}. This matches "hello", so they form a group. 5. Analyze "world": character counts are {w:1, o:1, r:1, l:1, d:1}. No other string matches this profile, so it forms its own group. 6. The final output contains three groups.

Example 2
Input
words = ["a", "b", "a", "b", "c"]
Output
[["a", "a"], ["b", "b"], ["c"]]

Explanation: 1. "a" has profile {a:1}. 2. "b" has profile {b:1}. 3. The second "a" has profile {a:1}, matching the first "a". 4. The second "b" has profile {b:1}, matching the first "b". 5. "c" has profile {c:1}, which is unique. 6. The groups are formed based on these unique profiles.

Example 3
Input
words = ["abc", "bca", "cab", "xyz", "zyx"]
Output
[["abc", "bca", "cab"], ["xyz", "zyx"]]

Explanation: 1. "abc" has profile {a:1, b:1, c:1}. 2. "bca" has profile {b:1, c:1, a:1}, which is identical to "abc". 3. "cab" has profile {c:1, a:1, b:1}, which is identical to "abc". 4. These three strings form one group. 5. "xyz" has profile {x:1, y:1, z:1}. 6. "zyx" has profile {z:1, y:1, x:1}, which is identical to "xyz". 7. These two strings form a second group.

Example 4
Input
words = ["aab", "aba", "baa", "abb"]
Output
[["aab", "aba", "baa"], ["abb"]]

Explanation: 1. "aab" has profile {a:2, b:1}. 2. "aba" has profile {a:2, b:1}, matching "aab". 3. "baa" has profile {b:1, a:2}, matching "aab". 4. These three strings form one group. 5. "abb" has profile {a:1, b:2}, which is distinct from the previous group. 6. "abb" forms its own group.

Constraints

  • 1 <= words.length <= 10^4
  • 1 <= words[i].length <= 100
  • words[i] consists of lowercase English letters only.
  • The total sum of words[i].length will not exceed 10^6.
Live Compiler1 Free Run Available
Loading Editor...
Test Cases & Output
Click "Run" to test your 1 free compile trial!

🚀 Practice this problem

Run code, get AI hints & track streak

Sign Up Free

Categorical Array Segmentation — Problem Statement & Solution Guide

StringsMediumGroup Anagrams
TimeO(N * L)
|
SpaceO(N * K)

Problem Description

You are provided with an array of strings, where each string consists solely of lowercase English letters. Your objective is to partition these strings into distinct clusters based on their character frequency profiles. Two strings are considered equivalent and must be placed in the same cluster if and only if they are anagrams of each other. This means that for any two strings in the same cluster, the count of every character from 'a' to 'z' must be identical, regardless of the order in which the characters appear within the string.

The grouping logic relies on the multiset of characters contained in each string. If string A contains two 'a's, one 'b', and no other characters, and string B also contains two 'a's, one 'b', and no other characters, they belong to the same group, even if A is "aab" and B is "aba". Conversely, if the frequency of any single character differs between two strings, they must reside in separate groups.

Return a list of lists, where each inner list contains all strings from the input array that share the same character composition. The order of the groups in the returned list does not matter, nor does the order of strings within each group. However, every string from the input must appear exactly once in the output.

DSA Pattern Breakdown

DSA Pattern Breakdown

"Categorical Array Segmentation"

medium

WHY DOES IT MATTER?

Grouping by character frequency is a fundamental pattern for problems that require equivalence classification based on content rather than order. Mastering this pattern enables candidates to solve a wide range of clustering, deduplication, and pattern‑matching challenges efficiently.

OPTIMIZATION CHALLENGE

The breakthrough is replacing O(L log L) sorting with O(L) counting using a fixed‑size alphabet. This reduces the per‑string cost dramatically and eliminates the hidden logarithmic factor, making the solution scalable to massive inputs.

REAL-WORLD CONNECTION

Think of a distributed log‑aggregation service that needs to bucket log messages with identical error signatures. By hashing the normalized error signature (similar to an anagram key), the system can route related logs to the same processing pipeline, reducing latency and storage overhead.

When coding, build the frequency signature as a tuple of 26 integers (or a string like "#1#0#3...") to guarantee hashability; avoid converting the count array to a list before using it as a dict key, as lists are unhashable in most languages.

COMPLEXITY AT A GLANCE

⏱ Time:O(N * L)
💾 Space:O(N * K)

Core Theory — Why This Approach?

The core of this problem lies in recognizing that two strings belong to the same cluster if they share an identical multiset of characters, i.e., they are anagrams. The most efficient way to capture a string's character frequency profile is to construct a 26‑element integer vector (or a canonical sorted representation) that counts occurrences of each lowercase letter. By using this vector as a hashable key, we can group strings in linear time relative to the total number of characters. Naïve pairwise comparison of every string against every other would require O(n^2 * L) time (where L is average length), which quickly becomes infeasible for large n (10^5) and long strings. The optimal paradigm leverages a hash map (or dictionary) where each key is the frequency signature and the value is a list of indices or strings belonging to that cluster, achieving O(N * L) time and O(N) auxiliary space.

When implementing the signature, sorting each string yields a canonical form but incurs O(L log L) per string, inflating the overall complexity. A linear‑time counting approach—building a 26‑length array and converting it to a string or tuple—preserves O(L) per string while still providing a unique identifier for anagrams. This technique is a classic example of the "group by frequency" pattern, which appears in many interview problems such as "Group Anagrams" and "Find Duplicate Subtrees". Understanding why the counting method dominates sorting for fixed‑size alphabets is essential for scaling solutions to massive datasets.

Interview Questions on This Problem

Q1How would you modify the solution if the strings could contain both uppercase and lowercase letters, and you needed case‑insensitive grouping?

Normalize each character to a common case (e.g., lowercase) before counting frequencies. Expand the frequency vector to 52 slots if case‑sensitivity is required, or keep 26 slots after conversion for case‑insensitive grouping. The rest of the algorithm remains unchanged.

Q2Explain how you would adapt the algorithm to work with Unicode characters beyond the English alphabet while still maintaining linear time per string.

Use a hash map to count character occurrences instead of a fixed‑size array. For each string, iterate over its Unicode code points, increment counts in a map, then serialize the map (e.g., sorted key‑value pairs) to form a deterministic signature. The per‑string cost stays O(L) but the constant factor grows with the number of distinct characters.

Q3In a distributed system processing billions of strings, how can you efficiently group anagrams without moving all data to a single node?

Apply a map‑reduce style approach: each mapper computes the signature locally and emits (signature, string) pairs. The shuffle phase groups pairs by signature across the cluster, and reducers aggregate the strings for each signature. This leverages the same hashing principle while distributing both computation and data.

Examples

Example 1

Input

words = ["listen", "silent", "hello", "olleh", "world"]

Output

[["listen", "silent"], ["hello", "olleh"], ["world"]]

Explanation: 1. Analyze "listen": character counts are {l:1, i:1, s:1, t:1, e:1, n:1}. 2. Analyze "silent": character counts are {s:1, i:1, l:1, e:1, n:1, t:1}. This matches "listen", so they form a group. 3. Analyze "hello": character counts are {h:1, e:1, l:2, o:1}. 4. Analyze "olleh": character counts are {o:1, l:2, e:1, h:1}. This matches "hello", so they form a group. 5. Analyze "world": character counts are {w:1, o:1, r:1, l:1, d:1}. No other string matches this profile, so it forms its own group. 6. The final output contains three groups.

Example 2

Input

words = ["a", "b", "a", "b", "c"]

Output

[["a", "a"], ["b", "b"], ["c"]]

Explanation: 1. "a" has profile {a:1}. 2. "b" has profile {b:1}. 3. The second "a" has profile {a:1}, matching the first "a". 4. The second "b" has profile {b:1}, matching the first "b". 5. "c" has profile {c:1}, which is unique. 6. The groups are formed based on these unique profiles.

Example 3

Input

words = ["abc", "bca", "cab", "xyz", "zyx"]

Output

[["abc", "bca", "cab"], ["xyz", "zyx"]]

Explanation: 1. "abc" has profile {a:1, b:1, c:1}. 2. "bca" has profile {b:1, c:1, a:1}, which is identical to "abc". 3. "cab" has profile {c:1, a:1, b:1}, which is identical to "abc". 4. These three strings form one group. 5. "xyz" has profile {x:1, y:1, z:1}. 6. "zyx" has profile {z:1, y:1, x:1}, which is identical to "xyz". 7. These two strings form a second group.

Example 4

Input

words = ["aab", "aba", "baa", "abb"]

Output

[["aab", "aba", "baa"], ["abb"]]

Explanation: 1. "aab" has profile {a:2, b:1}. 2. "aba" has profile {a:2, b:1}, matching "aab". 3. "baa" has profile {b:1, a:2}, matching "aab". 4. These three strings form one group. 5. "abb" has profile {a:1, b:2}, which is distinct from the previous group. 6. "abb" forms its own group.

Constraints

  • 1 <= words.length <= 10^4
  • 1 <= words[i].length <= 100
  • words[i] consists of lowercase English letters only.
  • The total sum of words[i].length will not exceed 10^6.

Optimal Approach & Strategy

Compute a 26‑letter frequency signature for each string and use it as a hash map key, achieving O(N * L) time and O(N) extra space.

Brute Force Approach

Compare every pair of strings, sorting each pair to check for anagram equality, which leads to O(n^2 * L log L) time.

Verified Code Solutions

JavaScript Solution
Time: O(N * L)
function solution(strs) {
      const map = new Map();
      for (const str of strs) {
         const sortedStr = [...str].sort().join('');
         if (!map.has(sortedStr)) {
            map.set(sortedStr, []);
         }
         map.get(sortedStr).push(str);
      }
      return Array.from(map.values());
   }

Solve in Interative Editor

Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.