Minimum Length of Anagram Concatenation

MEDIUM

Description

You are given a string s, which is known to be a concatenation of anagrams of some string t.

Return the minimum possible length of the string t.

An anagram is formed by rearranging the letters of a string. For example, "aab", "aba", and, "baa" are anagrams of "aab".

 

Example 1:

Input: s = "abba"

Output: 2

Explanation:

One possible string t could be "ba".

Example 2:

Input: s = "cdef"

Output: 4

Explanation:

One possible string t could be "cdef", notice that t can be equal to s.

Example 2:

Input: s = "abcbcacabbaccba"

Output: 3

 

Constraints:

  • 1 <= s.length <= 105
  • s consist only of lowercase English letters.

Approaches

Checkout 3 different approaches to solve Minimum Length of Anagram Concatenation. Click on different approaches to view the approach and algorithm in detail.

Approach 1: Checking Divisors with Sorting

A straightforward approach is to test every possible length k for the string t. Since s is a concatenation of anagrams of t, the length of t, k, must be a divisor of the length of s, n. We can iterate through all divisors of n from smallest to largest. For each potential length k, we verify if s can be partitioned into n/k segments, all of which are anagrams of the first segment s[0...k-1]. Anagram checking is done by sorting each segment and comparing it to the sorted version of the first segment.

Algorithm

  • The fundamental observation is that if s is a concatenation of anagrams of a string t of length k, then k must be a divisor of the length of s, let's call it n.
  • This approach iterates through all possible lengths k that are divisors of n.
  • To check if two strings are anagrams, we can sort their characters. If the sorted strings are equal, they are anagrams.
  • The algorithm is as follows:
    1. Find all divisors of n = s.length().
    2. Sort the divisors in ascending order.
    3. For each divisor k: a. Take the first substring of length k, s.substring(0, k). Sort its characters to create a canonical representation, canonical_t. b. Iterate through the rest of the string in chunks of size k. c. For each chunk, sort its characters and compare it with canonical_t. d. If any chunk's sorted version doesn't match canonical_t, then k is not a valid length. We break and try the next larger divisor. e. If all chunks match, we have found the smallest possible length for t. We return k.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

class Solution {
    public int minAnagramLength(String s) {
        int n = s.length();
        List<Integer> divisors = findDivisors(n);
        Collections.sort(divisors);

        for (int k : divisors) {
            if (isPossible(s, k)) {
                return k;
            }
        }
        return n; // Should not be reached given problem constraints
    }

    private List<Integer> findDivisors(int n) {
        List<Integer> divisors = new ArrayList<>();
        for (int i = 1; i * i <= n; i++) {
            if (n % i == 0) {
                divisors.add(i);
                if (i * i != n) {
                    divisors.add(n / i);
                }
            }
        }
        return divisors;
    }

    private boolean isPossible(String s, int k) {
        int n = s.length();
        String firstSub = s.substring(0, k);
        char[] firstChars = firstSub.toCharArray();
        Arrays.sort(firstChars);
        String sortedFirst = new String(firstChars);

        for (int i = k; i < n; i += k) {
            String currentSub = s.substring(i, i + k);
            char[] currentChars = currentSub.toCharArray();
            Arrays.sort(currentChars);
            String sortedCurrent = new String(currentChars);
            if (!sortedFirst.equals(sortedCurrent)) {
                return false;
            }
        }
        return true;
    }
}

Complexity Analysis

Time Complexity: O(d(n) * n log n). Finding divisors takes `O(sqrt(n))`. For each of the `d(n)` divisors, we perform a check. The check for a given length `k` involves `n/k` substrings. Sorting each substring of length `k` takes `O(k log k)`. Thus, the check costs `O((n/k) * k log k) = O(n log k)`. The total complexity is dominated by checks for larger `k`, approaching `O(d(n) * n log n)`.Space Complexity: O(d(n) + n). `O(d(n))` to store the divisors, where `d(n)` is the number of divisors of `n`. Additionally, `O(k)` space is required for character arrays during sorting, which can be up to `O(n)` in the worst case.

Pros and Cons

Pros:
  • Conceptually simple and easy to follow.
  • Correctly identifies the minimal length by checking divisors in increasing order.
Cons:
  • The process of creating substrings and sorting them repeatedly is computationally expensive.
  • Time complexity is high, making it unsuitable for large inputs as it might lead to a 'Time Limit Exceeded' error.

Code Solutions

Checking out 3 solutions in different languages for Minimum Length of Anagram Concatenation. Click on different languages to view the code.


Video Solution

Watch the video walkthrough for Minimum Length of Anagram Concatenation



Patterns:

Counting

Data Structures:

Hash TableString

Companies:

Subscribe to Scale Engineer newsletter

Learn about System Design, Software Engineering, and interview experiences every week.

No spam, unsubscribe at any time.