一、描述
1.如果字符串中不含有任何 ‘aaa’,‘bbb’ 或 ‘ccc’ 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」
2.给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 s:
s 是一个尽可能长的快乐字符串。
s 中 最多 有a 个字母 ‘a’、b 个字母 ‘b’、c 个字母 ‘c’ 。
s 中只含有 ‘a’、‘b’ 、‘c’ 三种字母。
3.输入:a = 1, b = 1, c = 7
输出:“ccaccbcc"或者"ccbccacc”
// 0 <= a, b, c <= 100
// a + b + c > 0
二、解
简单来说就是给定a,b,c三个字符的数量,让我们去构成不含三个相同字符在一起的字符串,并且尽可能长
1.怎样构成的字符串最长
贪心策略:
(可以简单的看出,多的字符比少的字符用的次数多才行,这样才能构成最长)
每次选择个数最多的字符
情况1:一直到各个字符都为0,返回结果
情况2:当当前字符和字符串前两个字符相同(会构成aaa/…)时,选择第二个最多的字符,继续下一次判断;如果没有其他字符可选,返回结果
2怎样每次拿到最大剩余字符和最大剩余字符的下一个
1.用集合或者数组存放字符和个数,使用Comparator定义排序规则,使用时直接取第一个/第二个即可(不会取第三个)
2.优先队列PriorityQueue,(也是使用Comparator定义排序规则)
优先队列:
public static void main(String[] args) {
int a = 1, b = 1, c = 7;
System.out.println(longestDiverseString(a,b,c));
}
public static String longestDiverseString(int a, int b, int c) {
StringBuilder sb = new StringBuilder();
//注意Comparator<int[]>()使用int[]类型泛型,不然方法参数是object类型
// PriorityQueue<int[]> priorityQueue = new PriorityQueue<>(new Comparator<int[]>() {
// @Override
// public int compare(int[] a1, int[] a2) {
// return a2[0]-a1[0];
// }
// });
//构建个数从小到大的优先队列,每次取的都会是最大的
PriorityQueue<int[]> priorityQueue = new PriorityQueue<>((a1, a2) -> a2[0]-a1[0]);
if (a>0){
//int数组将char转为了int
priorityQueue.add(new int[]{a,'a'});
}
if (b>0){
priorityQueue.add(new int[]{b,'b'});
}
if (c>0){
priorityQueue.add(new int[]{c,'c'});
}
//队列为空时退出
while (!priorityQueue.isEmpty()){
int[] curChar =priorityQueue.poll();
int len = sb.length();
//达到重复3个,前两个字符已经相同
if (len>=2&&curChar[1]==sb.charAt(len-1)&&curChar[1]==sb.charAt(len-2)){
//没有其他字符,直接返回
if (priorityQueue.isEmpty()){
break;
}
int[] nextChar = priorityQueue.poll();
sb.append((char)nextChar[1]);
//这个字符剩余大于0才放回,否则就不放回
if ((--nextChar[0])!=0){
priorityQueue.add(nextChar);
}
//放回没用到的char
priorityQueue.add(curChar);
}else {
//未达到重复3个
sb.append((char)curChar[1]);
if ((--curChar[0])!=0){
priorityQueue.add(curChar);
}
}
}
return sb.toString();
}
81 13 O(n∗k∗logC) O(1)
Tips
1.Comparator:
public interface Comparator
用于对集合进行排序,简单来说集合里加了这个就能自动排序了
主要是他的compare()
排序规则:
使compare(x, y) <= 0,即两个元素返回结果<=0就是正序,内部可按需要实现
如这里的要让最大的位于前面,就让后面的元素个数减前面元素个数,因为后面元素小于前面的元素,为负为正序,否则后面元素大于前面的元素为正会交换顺序
2.PriorityQueue(优先队列)
有顺序的队列,顺序可以自定义
逻辑结构为二叉树
其他
其实只要能获取最大值和第二个最大值都能有结果,这样消耗时间击败100%,但繁琐也不优雅
public static String longestDiverseString1(int a, int b, int c) {
StringBuilder sb = new StringBuilder();
while(true){
char curChar = getMaxNumChar(a,b,c);
if (curChar==' '){
break;
}
int len = sb.length();
if (len>=2&&curChar==sb.charAt(len-1)&&curChar==sb.charAt(len-2)){
if (curChar=='a'){
a=a-101;
}else if (curChar=='b'){
b=b-101;
}else {
c=c-101;
}
char nextChar = getMaxNumChar(a,b,c);
if (nextChar==' '){
break;
}
sb.append(nextChar);
if (nextChar=='a'){
a=a-1;
}else if (nextChar=='b'){
b=b-1;
}else {
c=c-1;
}
if (curChar=='a'){
a=a+101;
}else if (curChar=='b'){
b=b+101;
}else {
c=c+101;
}
}else {
sb.append(curChar);
if (curChar=='a'){
a=a-1;
}else if (curChar=='b'){
b=b-1;
}else {
c=c-1;
}
}
}
return sb.toString();
}
//abc acb cab cba bac bca |A(3,3)
public static char getMaxNumChar(int a, int b, int c){
if (a>0&&a>=b&&a>c){
return 'a';
}else if(b>0&&b>=a&&b>=c) {
return 'b';
}else if(c>0){
return 'c';
}
return ' ';
}