✅Efficient🔥Beats 98,39%💡Beginner✅ C++ | Java | C# | Python🔥O(n) - O(1)
Algorithm consists of 2 steps:Step 1) - Setup
Create 2 int[] arrays, symbolCount and indices with size of 26 (number of letters in the alphabet).
And fill them
![image.png](https://assets.leetcode.com/users/images/8a5e31a7-5a68-4b9e-8e99-3949c83e2f3d_1734599204.5408463.png)

### Algorithm consists of 2 steps:

***Step 1)*** - Setup
Create 2 `int[]` arrays, `symbolCount` and `indices` with size of 26 (number of letters in the alphabet). 
And fill them in the following manner:
`symbolCount` stores count of each letter in `s`
`indices` is set up in such a way, so that every `[i-1]` element would refer to the closest nonempty element of `symbolCount`
**Example** - limit the number of letters to `6` for simplicity
If `s` is `aaaceccf`, than `symbolCount`would look like this: `[3,0,3,0,1,1]` and `indices` would look like this: `[0,0,2,2,4,5]`.

Again, every element of `indices` stores the index of closest nonempty element of `symbolCount`

***Step 2)*** - Iterate
After setup what is left is the main while loop. It has pretty descriptive comments in the code section, but I'll try to summarize the algorithm in simple language. Basically, it iterates over the `symbolCount` array, from right to left. Whenever `symbolCount[i] == 0` it changes `i` to the next nonempty element of `symbolCount` which is in fact `indices[i-1]`

Time complexity: $$O(n)$$
Space complexity: $$O(1)$$
<!-- Add your space complexity here, e.g. $$O(n)$$ -->

# Code
```csharp []
public string RepeatLimitedString(string s, int repeatLimit){
    StringBuilder sb = new StringBuilder();
    int[] symbolCount = new int[26];
    int[] indices = new int[26];
    int i = 0;

    for (; i < s.Length; i++) // Count total number of symbols in s
        symbolCount[(int)s[i] - 97]++;

    for (i = 1; i < 26; i++){ // Setup indices
        if (symbolCount[i] > 0)
            indices[i] = i;
        else
            indices[i] = indices[i-1];
    }

    i = 25;
    while (true){ // Loop for every letter 'z'->'a'
        if (symbolCount[i] <= 0) // Ran out of symbols
            i = indices[i - 1]; // Pick the next present llc 

        if (i == 0){ // i points to 'a', so we can no longer take llc from the left
            sb.Append((char)97, Math.Min(repeatLimit, symbolCount[0])); // Add whatever is left
            return sb.ToString();
        }

        while (symbolCount[i] > repeatLimit){ // Handle the case when we have more symbols than repeatLimit
            sb.Append((char)(i + 97), repeatLimit);
            symbolCount[i] -= repeatLimit;

            if (symbolCount[indices[i-1]] <= 0){ // If next llc is empty
                if (indices[i-1] <= 0) // If indices[i-1] points to 'a' => can't take the next llc
                    return sb.ToString();
                indices[i-1] = indices[indices[i-1]-1]; // Move to the next lexicographically largest
            }
            
            sb.Append((char)(indices[i-1] + 97)); // Add "filler" character
            symbolCount[indices[i-1]]--;
        }
        sb.Append((char)(i + 97), symbolCount[i]); // Add remaining characters
        symbolCount[i] = 0;
    }
}
```
```C++ []
string repeatLimitedString(string s, int repeatLimit) {
    std::string result;
    int symbolCount[26] = {0};
    int indices[26] = {0};
    
    for (char c : s) { // Count total number of symbols in s
        symbolCount[c - 'a']++;
    }


    for (int i = 1; i < 26; i++) { // Setup indices
        if (symbolCount[i] > 0)
            indices[i] = i;
        else
            indices[i] = indices[i - 1];
    }

    int i = 25;
    while (true) { // Loop for every letter 'z'->'a'
        if (symbolCount[i] <= 0) { // Ran out of symbols
            i = indices[i - 1]; // Pick the next present llc
        }

        if (i == 0) { // i points to 'a', so we can no longer take llc from the left
            result.append(std::min(repeatLimit, symbolCount[0]), 'a'); // Add whatever is left
            return result;
        }

        while (symbolCount[i] > repeatLimit) { // Handle the case when we have more symbols than repeatLimit
            result.append(repeatLimit, 'a' + i);  // Add the character
            symbolCount[i] -= repeatLimit;

            if (symbolCount[indices[i - 1]] <= 0) { // If next llc is empty
                if (indices[i - 1] <= 0) // If indices[i-1] points to 'a' => can't take the next llc
                    return result;
                indices[i - 1] = indices[indices[i - 1] - 1]; // Move to the next lexicographically largest
            }

            result.push_back('a' + indices[i - 1]); // Add "filler" character
            symbolCount[indices[i - 1]]--;
        }

        result.append(symbolCount[i], 'a' + i); // Add remaining characters
        symbolCount[i] = 0;
    }
}
```
```Java []
public String repeatLimitedString(String s, int repeatLimit) {
    StringBuilder sb = new StringBuilder();
    int[] symbolCount = new int[26];
    int[] indices = new int[26];
    int i = 0;

    for (; i < s.length(); i++) // Count total number of symbols in s
        symbolCount[s.charAt(i) - 'a']++;

    for (i = 1; i < 26; i++) { // Setup indices
        if (symbolCount[i] > 0)
            indices[i] = i;
        else
            indices[i] = indices[i - 1];
    }

    i = 25;
    while (true) { // Loop for every letter 'z'->'a'
        if (symbolCount[i] <= 0) // Ran out of symbols
            i = indices[i - 1]; // Pick the next present llc 

        if (i == 0) { // i points to 'a', so we can no longer take llc from the left
            sb.append(String.valueOf((char) ('a' + 0)).repeat(Math.min(repeatLimit, symbolCount[0]))); // Add whatever is left
            return sb.toString();
        }

        while (symbolCount[i] > repeatLimit) { // Handle the case when we have more symbols than repeatLimit
            sb.append(String.valueOf((char) ('a' + i)).repeat(repeatLimit));
            symbolCount[i] -= repeatLimit;

            if (symbolCount[indices[i - 1]] <= 0) { // If next llc is empty
                if (indices[i - 1] <= 0) // If indices[i-1] points to 'a' => can't take the next llc
                    return sb.toString();
                indices[i - 1] = indices[indices[i - 1] - 1]; // Move to the next lexicographically largest
            }

            sb.append((char) ('a' + indices[i - 1])); // Add "filler" character
            symbolCount[indices[i - 1]]--;
        }
        sb.append(String.valueOf((char) ('a' + i)).repeat(symbolCount[i])); // Add remaining characters
        symbolCount[i] = 0;
    }
}
```
```Python []
def repeatLimitedString(self, s: str, repeatLimit: int) -> str:
    sb = []
    symbol_count = [0] * 26
    indices = [0] * 26
    i = 0

    # Count total number of symbols in s
    for char in s:
        symbol_count[ord(char) - 97] += 1

    # Setup indices
    for i in range(1, 26):
        if symbol_count[i] > 0:
            indices[i] = i
        else:
            indices[i] = indices[i - 1]

    i = 25
    while True:  # Loop for every letter 'z' -> 'a'
        if symbol_count[i] <= 0:  # Ran out of symbols
            i = indices[i - 1]  # Pick the next present lexicographically largest character

        if i == 0:  # i points to 'a', so we can no longer take lexicographically largest from the left
            sb.append(chr(97) * min(repeatLimit, symbol_count[0]))  # Add whatever is left
            return ''.join(sb)

        while symbol_count[i] > repeatLimit:  # Handle the case when we have more symbols than repeatLimit
            sb.append(chr(i + 97) * repeatLimit)
            symbol_count[i] -= repeatLimit

            if symbol_count[indices[i - 1]] <= 0:  # If next lexicographically largest character is empty
                if indices[i - 1] <= 0:  # If indices[i-1] points to 'a' => can't take the next lexicographically largest
                    return ''.join(sb)
                indices[i - 1] = indices[indices[i - 1] - 1]  # Move to the next lexicographically largest

            sb.append(chr(indices[i - 1] + 97))  # Add "filler" character
            symbol_count[indices[i - 1]] -= 1

        sb.append(chr(i + 97) * symbol_count[i])  # Add remaining characters
        symbol_count[i] = 0

```
['Python', 'C++', 'Java', 'C#']