2182. 构造限制重复的字符串
给你一个字符串 s
和一个整数 repeatLimit
,用 s
中的字符构造一个新字符串 repeatLimitedString
,使任何字母 连续 出现的次数都不超过 repeatLimit
次。你不必使用 s
中的全部字符。
返回 字典序最大的 repeatLimitedString
。
如果在字符串 a
和 b
不同的第一个位置,字符串 a
中的字母在字母表中出现时间比字符串 b
对应的字母晚,则认为字符串 a
比字符串 b
字典序更大 。如果字符串中前 min(a.length, b.length)
个字符都相同,那么较长的字符串字典序更大。
示例一:
输入:s = "cczazcc", repeatLimit = 3 输出:"zzcccac" 解释:使用 s 中的所有字符来构造 repeatLimitedString "zzcccac"。 字母 'a' 连续出现至多 1 次。 字母 'c' 连续出现至多 3 次。 字母 'z' 连续出现至多 2 次。 因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。 该字符串是字典序最大的 repeatLimitedString ,所以返回 "zzcccac" 。 注意,尽管 "zzcccca" 字典序更大,但字母 'c' 连续出现超过 3 次,所以它不是一个有效的 repeatLimitedString 。示例二:
输入:s = "aababab", repeatLimit = 2 输出:"bbabaa" 解释: 使用 s 中的一些字符来构造 repeatLimitedString "bbabaa"。 字母 'a' 连续出现至多 2 次。 字母 'b' 连续出现至多 2 次。 因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。 该字符串是字典序最大的 repeatLimitedString ,所以返回 "bbabaa" 。 注意,尽管 "bbabaaa" 字典序更大,但字母 'a' 连续出现超过 2 次,所以它不是一个有效的 repeatLimitedString 。提示:
1 <= repeatLimit <= s.length <= 105
s
由小写英文字母组成
1.和官方题解雷同,先统计频次,再从后往前加。摘录思路解释如下:
每次选择当前剩余的字典序最大的字符加到字符串末尾;如果字符串末尾的字符已经连续出现了 repeatLimit次,则将字典序次大的字符加到字符串末尾,随后继续选择当前剩余的字典序最大的字符加到字符串末尾,直至使用完字符或没有新的字符可以合法加入。
解释:根据反证法,我们只需要证明任意比上述方法构造出的字符串 ret的字典序更大的字符串都是不合法的即可。
根据字典序的定义,上述证明可以分为两部分:
1.从高位至低位逐位尝试使用字典序更大的字符替代,并逐个判断;
2.尝试在 ret 后添加新的字符,并逐个判断。
对于第一部分,任何使用更大的字符替代后的字符串要么使用了 sss 中不存在的字符,要么某一字符连续出现的次数大于 repeatLimit次,而这两种都是不合法的;对于第二部分,任何尝试添加新字符的字符串也一定是第一部分的两种情况之一,因而也是不合法的。
综上所述,按照上文方法构造的字符串的字典序一定是最大的。
说实话,没看太懂,但思路是这样的哈!
class Solution(object):
def repeatLimitedString(self, s, repeatLimit):
"""
:type s: str
:type repeatLimit: int
:rtype: str
"""
#构建一个存储字符频次的数组,0处存放“a”的频次
count=[0]*26
for i in s:
count[ord(i)-ord('a')]+=1
repe=[]
i,j,m=25,24,0#加入新船的时候要从后往前选择加入,因为后面的字符字典序更大
#m是指当前填充数字的数量
while i>=0 and j >=0:
if count[i]==0:
m,i=0,i-1#不填这个数字了,所以要重新计算m
elif m < repeatLimit:#如果没超过限制
count[i]-=1
repe.append(chr(ord('a')+i))#把这个字符加进去
m+=1
elif j>=i or count[j] == 0:#当前字符已经超过限制,查找可填入的其他字符
j-=1
else:#当前字符已经查过限制,需要其他字符填充进去,这时需要重置m
count[j]-=1
repe.append(chr(ord('a')+j))
m=0
return ''.join(repe)
python
from collections import Counter, deque
class Solution:
def repeatLimitedString(self, s: str, repeatLimit: int) -> str:
count = Counter(s)
count = sorted(count.items(), reverse=True)
count = deque(count)
res = ""
while count:
char, time = count.popleft()
if time > repeatLimit and count:
char2, time2 = count.popleft()
if time2 > 1:
count.appendleft((char2, time2-1))
count.appendleft((char, time-repeatLimit))
count.appendleft((char2, 1))
else:
count.appendleft((char, time-repeatLimit))
count.appendleft((char2, 1))
res += char*min(time, repeatLimit)
return res
还有java:
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();
}
}