题目来源:https://leetcode-cn.com/problems/longest-happy-string/
大致题意:
给定 a b c 三个字母的数目,按照如下要求构造一个最长的字符串:
- 不能有连续三个字母相同
- 每种字母数目不能超过给定数目
- 只能使用 a b c
思路
要想字符串尽可能长,那么就要尽可能把所有能用的字母都用上,而又限制了相同字母最多连续 3 个,所以要尽可能把数量最多的字母安排的多一些,最后构成的字符串,要么长度和给定字母数量相同,要么因为无法安排全部的最多数量的字母,造成长度小于给定数量
于是可以使用贪心的思路,每次安排字母的时候,都尽可能安排目前可用字母中数量最多的
贪心
- 构建一个内部类,用来表示字母和对应数量
- 循环安排字母,每次在保证规则的前提下,优先安排剩余数量最多的字母,如果本轮没有可用字母,那么退出循环
- 此时字符串即为最长满足题意的字符串
代码:
public class LongestDiverseString {
public String longestDiverseString(int a, int b, int c) {
Pair[] pairs = new Pair[3];
// 初始化
pairs[0] = new Pair(a, 'a');
pairs[1] = new Pair(b, 'b');
pairs[2] = new Pair(c, 'c');
StringBuffer sb = new StringBuffer();
while (true) {
// 每次都对数组降序排序
Arrays.sort(pairs, (x, y) -> y.freq - x.freq);
// 标记本轮是否放入字母
boolean hasNext = false;
int len = sb.length();
// 优先放入剩余数量最多的字母
for (int i = 0; i < 3; i++) {
char ch = pairs[i].c;
// 检查是否满足规则
if (pairs[i].freq == 0 || len >= 2 && sb.charAt(len - 2) == ch && sb.charAt(len - 1) == ch) {
continue;
}
// 放入当前字母
sb.append(ch);
// 更新数量
pairs[i].freq--;
// 更新标记
hasNext = true;
break;
}
// 若没有放入字母,跳出循环
if (!hasNext) {
break;
}
}
return sb.toString();
}
// 构建用来表示字母和对应数量的类
class Pair {
int freq;
char c;
public Pair(int freq, char c) {
this.freq = freq;
this.c = c;
}
}
}