Construct String With Repeat Limit

Updated on 20 May, 2025
Construct String With Repeat Limit header image

Problem Statement

In this problem, you are provided with a string s and an integer repeatLimit. Your task is to construct a new string named repeatLimitedString from the characters of s. This construction must adhere to the condition where no single letter is repeated more than repeatLimit times consecutively. It's not mandatory to use all characters from the original string s. The goal of this task is to form the lexicographically largest repeatLimitedString that is possible under the given constraints.

To better understand, a string a is considered lexicographically larger than string b if at any position where they differ, the string a has a character that is later in the alphabet than the corresponding character in b. If their characters don't differ up to the shortest string's length, then the longer string is deemed larger.

Examples

Example 1

Input:

s = "cczazcc", repeatLimit = 3

Output:

"zzcccac"

Explanation:

We use all of the characters from s to construct the repeatLimitedString "zzcccac".
The letter 'a' appears at most 1 time in a row.
The letter 'c' appears at most 3 times in a row.
The letter 'z' appears at most 2 times in a row.
Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString.
The string is the lexicographically largest repeatLimitedString possible so we return "zzcccac".
Note that the string "zzcccca" is lexicographically larger but the letter 'c' appears more than 3 times in a row, so it is not a valid repeatLimitedString.

Example 2

Input:

s = "aababab", repeatLimit = 2

Output:

"bbabaa"

Explanation:

We use only some of the characters from s to construct the repeatLimitedString "bbabaa".
The letter 'a' appears at most 2 times in a row.
The letter 'b' appears at most 2 times in a row.
Hence, no letter appears more than repeatLimit times in a row and the string is a valid repeatLimitedString.
The string is the lexicographically largest repeatLimitedString possible so we return "bbabaa".
Note that the string "bbabaaa" is lexicographically larger but the letter 'a' appears more than 2 times in a row, so it is not a valid repeatLimitedString.

Constraints

  • 1 <= repeatLimit <= s.length <= 105
  • s consists of lowercase English letters.

Approach and Intuition

  1. Character Frequency Counting: First, count the frequency of each character in string s. This helps us understand how many times we can potentially use each character in the desired output string without violating the repeat limit.

  2. Sorting and Priority: Since we need the lexicographically largest string, we should process the characters from the highest (e.g. z) to the lowest (e.g. a). Utilizing a max-heap (or sorting characters in reverse order) allows us to always pick the largest available character first.

  3. Building the Result String: Start constructing the new string by repeatedly appending the largest available character:

    • Add the character up to repeatLimit times (or less if fewer are available).
    • If the same character cannot be used again immediately (because it would exceed the repeatLimit), introduce a different character (next largest available) to break the sequence.
    • Continue this pattern until no valid addition to the string is possible either because we run out of characters or can't add another character without violating the repeat limit.
  4. Considerations for Lexicographical Order:

    • Always prioritize adding the highest possible character.
    • When forced to break a sequence (to adhere to the repeatLimit), choose the next highest character that doesn't violate the rules.
  5. Edge Cases:

    • If repeatLimit is 1, you can't use the same character twice in a row, which essentially makes the result string an alternation of different characters.
    • High character frequency and a low repeatLimit might lead to unused characters.
    • Characters might need to be skipped if they risk creating violations of the repeatLimit even if they are lexicographically advantageous.

This structured approach ensures the lexicographically largest sequence possible while complying with the repeat limit constraints. With careful management of character selection and sequencing, the desired output can be achieved efficiently.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    string constructLimitedString(string str, int limit) {
        unordered_map<char, int> charCount;
        for (char c : str) {
            charCount[c]++;
        }

        priority_queue<char> characters;
        for (auto& [character, freq] : charCount) {
            characters.push(character);
        }

        string output;
        while (!characters.empty()) {
            char current = characters.top();
            characters.pop();
            int availableCount = charCount[current];

            int useCount = min(availableCount, limit);
            output.append(useCount, current);

            charCount[current] -= useCount;

            if (charCount[current] > 0 && !characters.empty()) {
                char nextCharacter = characters.top();
                characters.pop();

                output.push_back(nextCharacter);
                charCount[nextCharacter]--;

                if (charCount[nextCharacter] > 0) {
                    characters.push(nextCharacter);
                }

                characters.push(current);
            }
        }

        return output;
    }
};

This solution describes how to construct a string with a repeat limit, using C++ as the programming language. The solution accomplishes this by leveraging a priority queue to manage the characters based on their frequency in descending order, thus ensuring the highest frequency characters are processed first.

Here's a breakdown of how the solution works:

  • Generate a count of each character in the input string using an unordered_map, where the key is the character and the value is its count.
  • Populate a priority_queue with characters based on the character counts. This allows characters with higher frequencies to be prioritized.
  • Use a loop to repeatedly pick characters from the priority_queue. On each iteration:
    1. Remove the top character, which has the highest remaining frequency.
    2. Append this character to the result string up to the given limit.
    3. Reduce the count of this used character.
    4. If there are still instances of this character left (after applying the limit):
      • Temporarily use the next highest frequency character (if available) to ensure no character is repeated more than the specified limit in succession.
      • After appending this next character, check if it still needs to be reinserted into the priority queue for future consideration along with the original character, which is reinserted as well.
  • Continue the process until all characters are used or no valid characters remain to be appended while respecting the repeat limit.

The solution handles the constraints efficiently, ensuring that each character does not appear consecutively more than the allowed limit, while also managing the sequence in which characters appear in the output to maximize usage of higher frequency characters early on. This approach efficiently constructs the desired output string while adhering to the specified repeat constraints.

java
class Solution {

    public String constructStringWithLimits(String inputString, int maxRepeats) {
        Map<Character, Integer> charCount = new HashMap<>(); 
        for (char character : inputString.toCharArray()) {
            charCount.put(character, charCount.getOrDefault(character, 0) + 1);
        }

        PriorityQueue<Character> descendingCharQueue = new PriorityQueue<>((x, y) -> y.compareTo(x));

        for (char character : charCount.keySet()) {
            descendingCharQueue.add(character);
        }

        StringBuilder output = new StringBuilder();

        while (!descendingCharQueue.isEmpty()) {
            char currentChar = descendingCharQueue.poll();
            int currentCount = charCount.get(currentChar);

            int instancesToUse = Math.min(currentCount, maxRepeats);
            for (int i = 0; i < instancesToUse; i++) {
                output.append(currentChar);
            }

            charCount.put(currentChar, currentCount - instancesToUse);

            if (charCount.get(currentChar) > 0 && !descendingCharQueue.isEmpty()) {
                char nextChar = descendingCharQueue.poll();
                output.append(nextChar);
                charCount.put(nextChar, charCount.get(nextChar) - 1);
                if (charCount.get(nextChar) > 0) {
                    descendingCharQueue.offer(nextChar);
                }
                descendingCharQueue.offer(currentChar);
            }
        }

        return output.toString();
    }
}

The provided Java solution outlines a method to create a string from the given input string such that no character repeats consecutively more than the specified limit. Here's the summary of the approach used in the solution:

  • Use a HashMap to count the frequency of each character in the input string.
  • Utilize a PriorityQueue to process characters in descending order based on their natural ordering.
  • Iterate over characters in priority, appending them to the result while respecting the maxRepeats limit.
  • After the maximum allowed consecutive repeats of a character are appended, if the character still has remaining counts, it is temporarily skipped by introducing the next character from the queue to avoid consecutive repeats.
  • Continue the process until all characters are placed in the resulting string according to the constraints.

The major steps in the algorithm are:

  1. Count each character's occurrences in the input string.
  2. Initialize a max-heap (priority queue) to sort characters based on their ASCII values in descending order.
  3. Continue processing characters from the queue:
    • Append the current character up to the allowed limit (maxRepeats).
    • Place the next different character into the output to ensure no character is repeated consecutively beyond the allowed limit.
    • Re-insert characters back into the queue if they still have remaining counts.
  4. The loop exits when no characters are left to process, returning the constructed string that meets the conditions.
python
class Solution:
    def constructString(self, string: str, limit: int) -> str:
        max_pq = [(-ord(char), freq) for char, freq in Counter(string).items()]
        heapify(max_pq)
        output = []

        while max_pq:
            neg_val, freq = heappop(max_pq)
            actual_char = chr(-neg_val)
            use_limit = min(freq, limit)
            output.append(actual_char * use_limit)

            if freq > use_limit and max_pq:
                next_neg_val, next_freq = heappop(max_pq)
                output.append(chr(-next_neg_val))
                if next_freq > 1:
                    heappush(max_pq, (next_neg_val, next_freq - 1))
                heappush(max_pq, (neg_val, freq - use_limit))

        return "".join(output)

The solution is designed to create a string from specified input where no characters can repeat consecutively more than a given limit. Written in Python 3, the program uses a priority queue to manage character frequencies and order of appearance, ensuring the most frequent characters are processed first within the repeat constraints.

Follow the insights below for understanding the method:

  • Initialize a max priority queue that stores characters based on their ASCII negative values and their frequencies. This allows the most frequent character (highest frequency) to be accessed first.
  • Convert the string input into a count of occurrences using Counter from the collections module.
  • Iterate through the max priority queue:
    • Pop the character with the highest frequency.
    • Append the character to the output string restricted by the limit parameter. Use the minimum of the character's frequency or the limit.
    • If there's residual count left for that character (i.e., still more times this character needs to be appended but is constrained by limit), try to insert a different character from the priority queue to avoid consecutive repetitions.
    • Re-push the leftover frequency of characters back into the priority queue for future processing if needed.
  • Continue this process until the max priority queue is emptied.
  • Finally, concatenate all partial results to form the final output string.

This algorithm efficiently ensures that no single character repeats more than the limit consecutively while maintaining a greedy approach towards maximizing the use of higher frequency characters.

Comments

No comments yet.

2182. Construct String With Repeat Limit - Solutions and Explanation | Vultr Docs