You are given a string s
and an integer repeatLimit
. Construct a new string repeatLimitedString
using the characters of s
such that no letter appears more than repeatLimit
times in a row. You do not have to use all characters from s
.
Return the lexicographically largest repeatLimitedString
possible.
A string a
is lexicographically larger than a string b
if in the first position where a
and b
differ, string a
has a letter that appears later in the alphabet than the corresponding letter in b
. If the first min(a.length, b.length)
characters do not differ, then the longer string is the lexicographically larger one.
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.
First, we use an array
The time complexity is
class Solution:
def repeatLimitedString(self, s: str, repeatLimit: int) -> str:
cnt = [0] * 26
for c in s:
cnt[ord(c) - ord("a")] += 1
ans = []
j = 24
for i in range(25, -1, -1):
j = min(i - 1, j)
while 1:
x = min(repeatLimit, cnt[i])
cnt[i] -= x
ans.append(ascii_lowercase[i] * x)
if cnt[i] == 0:
break
while j >= 0 and cnt[j] == 0:
j -= 1
if j < 0:
break
cnt[j] -= 1
ans.append(ascii_lowercase[j])
return "".join(ans)
class Solution {
public String repeatLimitedString(String s, int repeatLimit) {
int[] cnt = new int[26];
for (int i = 0; i < s.length(); ++i) {
++cnt[s.charAt(i) - 'a'];
}
StringBuilder ans = new StringBuilder();
for (int i = 25, j = 24; i >= 0; --i) {
j = Math.min(j, i - 1);
while (true) {
for (int k = Math.min(cnt[i], repeatLimit); k > 0; --k) {
ans.append((char) ('a' + i));
--cnt[i];
}
if (cnt[i] == 0) {
break;
}
while (j >= 0 && cnt[j] == 0) {
--j;
}
if (j < 0) {
break;
}
ans.append((char) ('a' + j));
--cnt[j];
}
}
return ans.toString();
}
}
class Solution {
public:
string repeatLimitedString(string s, int repeatLimit) {
int cnt[26]{};
for (char& c : s) {
++cnt[c - 'a'];
}
string ans;
for (int i = 25, j = 24; ~i; --i) {
j = min(j, i - 1);
while (1) {
for (int k = min(cnt[i], repeatLimit); k; --k) {
ans += 'a' + i;
--cnt[i];
}
if (cnt[i] == 0) {
break;
}
while (j >= 0 && cnt[j] == 0) {
--j;
}
if (j < 0) {
break;
}
ans += 'a' + j;
--cnt[j];
}
}
return ans;
}
};
func repeatLimitedString(s string, repeatLimit int) string {
cnt := [26]int{}
for _, c := range s {
cnt[c-'a']++
}
var ans []byte
for i, j := 25, 24; i >= 0; i-- {
j = min(j, i-1)
for {
for k := min(cnt[i], repeatLimit); k > 0; k-- {
ans = append(ans, byte(i+'a'))
cnt[i]--
}
if cnt[i] == 0 {
break
}
for j >= 0 && cnt[j] == 0 {
j--
}
if j < 0 {
break
}
ans = append(ans, byte(j+'a'))
cnt[j]--
}
}
return string(ans)
}
function repeatLimitedString(s: string, repeatLimit: number): string {
const cnt: number[] = Array(26).fill(0);
for (const c of s) {
cnt[c.charCodeAt(0) - 97]++;
}
const ans: string[] = [];
for (let i = 25, j = 24; ~i; --i) {
j = Math.min(j, i - 1);
while (true) {
for (let k = Math.min(cnt[i], repeatLimit); k; --k) {
ans.push(String.fromCharCode(97 + i));
--cnt[i];
}
if (!cnt[i]) {
break;
}
while (j >= 0 && !cnt[j]) {
--j;
}
if (j < 0) {
break;
}
ans.push(String.fromCharCode(97 + j));
--cnt[j];
}
}
return ans.join('');
}