解法一:堆
这个做法真的很秒,把所有字符及其数量放入堆中,然后每次排出最大的两个元素,这样就不会有重复,真的惊了,太强的做法!这次用了python实现堆,学会了__lt__定义比较函数,python还是很香。
下图为python各种比较函数,由于py默认生成最小堆,咱们把小于号定义成大于关系就行。
from queue import PriorityQueue
class Solution:
def reorganizeString(self, S: str) -> str:
class node:
def __init__(self, c, ct):
self.c = c
self.ct = ct
# 这里定义的是大于号
def __lt__(self, other):
return self.ct > other.ct
mx = int((len(S)+1)/2)
d = {}
for c in S:
if c in d:
d[c] += 1
else:
d[c] = 1
q = PriorityQueue()
for c in d:
if d[c] > mx:
return ''
q.put(node(c, d[c]))
result = ''
while not q.empty():
if q.qsize() == 1:
result += q.get().c
return result
a, b = q.get(), q.get()
result += a.c
result += b.c
if a.ct > 1:
a.ct -= 1
q.put(a)
if b.ct > 1:
b.ct -= 1
q.put(b)
return result
解法二:维护
做法很简单,奇数位和偶数位分开考虑,非法情况很好判断,不再赘述。当有字符出现一半以上(仅奇数长度字符串可能出现),放入偶数索引。其余情况先填奇数,填满奇数填偶数就好。(非常贪心的一种做法)
from queue import PriorityQueue
class Solution:
def reorganizeString(self, S: str) -> str:
mx = int((len(S)+1)/2)
d = {}
for c in S:
if c in d:
d[c] += 1
else:
d[c] = 1
result = [None for _ in range(len(S))]
# 先放奇数位置,因为偶数位可能要放最大的。
p_even, p_odd = 0, 1
for c in d:
if d[c] > mx: return ''
if (len(S) & 1) and mx == d[c]:
while p_even < len(S):
result[p_even] = c
p_even += 2
else:
while p_odd < len(S) and d[c] > 0:
result[p_odd] = c
p_odd += 2
d[c] -= 1
while p_even < len(S) and d[c] > 0:
result[p_even] = c
p_even += 2
d[c] -= 1
return ''.join(result)