1 | 给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。 |
解题思路:
- 先把字符串进行桶计数
- 每次先选数量最多的,当前字符的计数减1
- 再选数量次多的一个字符(不和前一个相同),当前字符的计数减一
- 如果某一次选不到任何一个字符并且还没结束,那么就不能满足,直接返回空
1 | class Solution { |
基于最大堆的贪心算法(跟我的想法相似,但是实现更好)
维护最大堆存储字母,堆顶元素为出现次数最多的字母。首先统计每个字母的出现次数,然后将出现次数大于 0 的字母加入最大堆。
当最大堆的元素个数大于 1 时,每次从最大堆取出两个字母,拼接到重构的字符串,然后将两个字母的出现次数分别减 1,并将剩余出现次数大于 0 的字母重新加入最大堆。由于最大堆中的元素都是不同的,因此取出的两个字母一定也是不同的,将两个不同的字母拼接到重构的字符串,可以确保相邻的字母都不相同。
如果最大堆变成空,则已经完成字符串的重构。如果最大堆剩下 1 个元素,则取出最后一个字母,拼接到重构的字符串。
对于长度为 n 的字符串,共有 n/2 次每次从最大堆取出两个字母的操作,当 n 是奇数时,还有一次从最大堆取出一个字母的操作,因此重构的字符串的长度一定是 n。
当 n 是奇数时,是否可能出现重构的字符串的最后两个字母相同的情况?如果最后一个字母在整个字符串中至少出现了 2 次,则在最后一次从最大堆取出两个字母时,该字母会先被选出,因此不会成为重构的字符串的倒数第二个字母,也不可能出现重构的字符串最后两个字母相同的情况。
因此,在重构字符串可行的情况下,基于最大堆的贪心算法可以确保得到正确答案。
1 | class Solution { |
1 | class Solution { |
参考文献
作者:LeetCode-Solution
链接:来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。