首先通过计数排序的思路统计每个数字出现的次数,然后计算所有数字的总和。如果总和是3的倍数,那么就可以直接用这些数字组成最大的数。如果不是3的倍数,需要通过删除几个最小的数字来调整总和使其成为3的倍数。具体来说:
1. 计算总和模3的结果,如果余数为1,尝试先删除一个余数为1的数字,如果没有,再尝试删除两个余数为2的数字;如果余数为2,尝试先删除一个余数为2的数字,如果没有,再尝试删除两个余数为1的数字。
2. 删除数字后,按照从大到小的顺序组合剩余的数字,将结果转化为字符串。如果数字中包含0,则确保0只在最后出现,除非结果只有0。
3. 特别注意处理只有0或结果无法形成3的倍数的情况。
时间复杂度: O(n)
空间复杂度: O(1)
class Solution:
def largestMultipleOfThree(self, digits: List[int]) -> str:
counter = [0] * 10 # 用于统计每个数字的频率
for d in digits: # 统计频率
counter[d] += 1
s = sum(k * v for k, v in enumerate(counter) if k % 3 != 0) # 计算总和模3不为0的部分
mod1 = [1, 4, 7] # 余数为1的数字
mod2 = [2, 5, 8] # 余数为2的数字
excess = s % 3 # 总和模3的结果
if excess == 1: # 如果余数为1
if not any(counter[i] > 0 and counter[i] -= 1 for i in mod1): # 尝试删除一个模1的数字
k = 2
for i in mod2:
dif = min(counter[i], k)
counter[i] -= dif
k -= dif
if k == 0:
break
elif excess == 2: # 如果余数为2
if not any(counter[i] > 0 and counter[i] -= 1 for i in mod2): # 尝试删除一个模2的数字
k = 2
for i in mod1:
dif = min(counter[i], k)
counter[i] -= dif
k -= dif
if k == 0:
break
ret = []
for i in range(9, 0, -1): # 从大到小组合数字
if counter[i]:
ret.append(str(i) * counter[i])
if ret:
ret.append('0' * counter[0]) # 添加所有的0
else:
ret.append('0' * min(counter[0], 1)) # 只有0的情况
return ''.join(ret)