1405. 最长快乐字符串(2022-2-7)
如果字符串中不含有任何 '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” 也是一种正确答案。
解题思路
Object.entries()
:方法返回一个给定对象自身可枚举属性的键值对数组。类似于用了for in
MDN文档
这道题其实很容易看懂,无非就是贪心的思想,找到剩余数量最多的字符,去拼接到目标字符串上。
-
本题的第一个难点在于,将
a,b,c
进行排序,而且要始终维持一个降序的排列,起初我用的是一个字面量对象来表示{a : a}
字符与数量的关系,但是没法排序,看官方题解发现,用数组表示,其实更容易处理[[a,'a'],[b,'b']]
,还可以直接用sort()
排序。 -
通常我们默认会将字符两个两个的去拼接(因为是最优嘛),当不够一个的时候才拼接一个字符,其实这是个坑。因为两个两个去拼接,必定会剩下单数个,而这表明,两个两个拼接并不是局部最优(会错失正确答案例如
7,2,2
)。 -
我们换个思路,一个一个的去拼接,每次拼接的都是数量最多的字符,如果目标字符串中已经重复出现了两次,那么再拼接数量次多的字符。这样子代码也会更加好写,能少一些没必要的判断,更容易理解。
下面是我参照官方题解写的代码:
var longestDiverseString = function(a, b, c) {
const source = [[a,'a'],[b,'b'],[c,'c']]
let res = []
while(1){
source.sort((a,b)=> b[0] - a[0])
let next = false
for(let [i,[c,ch]] of source.entries()){
if(c == 0) break
let len = res.length
if(len >= 2 && res[len-1] == ch && res[len-2] == ch) continue
res.push(ch)
next = true
source[i][0]--
break
}
if(!next) break
}
return res.join('')
};
还有一种大顶堆的写法,用优先队列来维系降序的字符关系,我觉得有些大材小用了(太麻烦了)。
在这里附上优先队列的过程:
遇到不会的题,想不到的题很正常,关键在于下次是否想得到。