题目
给你一个字符串 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 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-string-with-repeat-limit
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法1:贪心+优先队列
字符串拼接尽量使用 StringBuffer 的append方法来拼接。
直接使用”+”来连接String类型会增加内存和CPU的开销。
Java实现
class Solution {
public String repeatLimitedString(String s, int repeatLimit) {
int n = s.length();
//存:{字符(-'a'),个数},按照字典序由大到小排序
PriorityQueue<int[]> q = new PriorityQueue<>((a, b)->{
return b[0] - a[0];
});
//统计每个字符出现次数
int[] count = new int[26];
for (char c : s.toCharArray()) {
count[c - 'a']++;
}
//将出现次数不为0的字母存进优先队列中
for (int i = 0; i < 26; i++) {
if (count[i] != 0) q.offer(new int[]{i, count[i]});
}
StringBuffer res = new StringBuffer();
while (!q.isEmpty()) {
int[] cur = q.poll();
int flag = 0;
while (cur[1] > 0 && flag < repeatLimit) {
cur[1]--;
flag++;
res.append((char)(cur[0] + 'a'));
}
if (cur[1] > 0 && !q.isEmpty()) {
int[] next = q.poll();
res.append((char)(next[0] + 'a'));
if (next[1] - 1 > 0) q.offer(new int[]{next[0], next[1] - 1});
q.offer(new int[]{cur[0], cur[1]});
}
}
return res.toString();
}
}