1. 问题描述:
如果字符串中不含有任何 'aaa','bbb' 或 'ccc' 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。
给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 s:
s 是一个尽可能长的快乐字符串。
s 中 最多 有a 个字母 'a'、b 个字母 'b'、c 个字母 'c' 。
s 中只含有 'a'、'b' 、'c' 三种字母。
如果不存在这样的字符串 s ,请返回一个空字符串 ""。
示例 1:
输入:a = 1, b = 1, c = 7
输出:"ccaccbcc"
解释:"ccbccacc" 也是一种正确答案。
示例 2:
输入:a = 2, b = 2, c = 1
输出:"aabbc"
示例 3:
输入:a = 7, b = 1, c = 0
输出:"aabaa"
解释:这是该测试用例的唯一正确答案。
提示:
0 <= a, b, c <= 100
a + b + c > 0
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-happy-string
2. 思路分析:
① 可能接触这一类的题目不是特点多,所以在一开始做的时候没啥思路,感觉挺复杂的,不像其他什么尝试可能的方案的题目可以使用dfs或者是是模拟的思路来解决,逛了一下评论区,基本上使用的是贪心的策略来解决的,其实仔细一想也是,使用贪心是有迹可循的,其实题目中的特点也是比较明显的,因为要组成尽可能长的字符串,所以我们在组成字符串的时候尽可能先拿取数量多的字母,这样的话形成的字符串也是最长的,并且先组成数量比较多的形成的冲突比数量少的要少,这些都是可以使用贪心策略解决的明显特点,下面是我参照评论区的C++大佬写的代码附上我的理解并且使用java语言重新写了一遍
② 知道了使用贪心策略之后那么接下来就可比较好解决了,可以使用一个数组来存储这些字母最多可以出现的次数,因为题目中存在一个限制条件最多能够三个相同的字母可以连在一起,所以需要声明一个变量来存储当前存在冲突的下标,当发现有两个字母相同的时候那么记录下这个下表,当尝试使用这个下标对应字母来拼接的时候需要跳过,需要尝试其他的字母来拼接,使用一个三次的循环来尝试拼接当前的字母,每一次在没有冲突的情况下都使用数量最大字母进行拼接,有冲突的时候尝试其他的字母,直到不能够拼接了那么就跳出循环了
③ 其实理解了这个贪心之后代码还是不难写出来的,而且感觉这道贪心的题目出得也非常巧妙,出得非常棒对理解贪心的思想很有帮助,恰好是三个字母
3. 代码如下:
class Solution {
public String longestDiverseString(int a, int b, int c) {
/*用来存放各个字符出现的次数*/
int numsCount[] = {a, b, c};
String res = "";
int index = 0, isconflict = -1;
while (true){
index = -1;
/*使用这个变量来记录冲突的下标*/
isconflict = -1;
if (res.length() > 1 && res.charAt(res.length() - 2) == res.charAt(res.length() - 1)) isconflict = res.charAt(res.length() - 1) - 'a';
for (int i = 0; i < 3; ++i){
/*当发现有冲突的时候直接跳过这个字母*/
if (numsCount[i] == 0 || isconflict == i) continue;
/*找出数量最大的那个字母来拼接*/
if (index == -1 || numsCount[i] > numsCount[index]) index = i;
}
/*等到所有不能够拿取数字的时候那么就会跳出循环*/
if (index == -1) break;
--numsCount[index];
res += (char)('a' + index);
}
return res;
}
}