1. 问题描述:
在一个仓库里,有一排条形码,其中第 i 个条形码为 barcodes[i]。请你重新排列这些条形码,使其中两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案,此题保证存在答案。
示例 1:
输入:[1,1,1,2,2,2]
输出:[2,1,2,1,2,1]
示例 2:
输入:[1,1,1,1,2,2,3,3]
输出:[1,3,1,3,2,1,2,1]
提示:
1 <= barcodes.length <= 10000
1 <= barcodes[i] <= 10000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/distant-barcodes
2. 思路分析:
① 分析题目可以知道这道题目与力扣的767题本质上是一样的,都是可以使用python中的heapq模块构建大根堆(当元素为int类型的时候将元置为负数那么就可以看成将小根堆看成是大根堆),首先需要使用字典来统计各个数字出现的次数,使用heapq模块将当前的数字与数字出现的次数对应的元组构成的列表初始化为一个堆,而且因为heapq模块创建的是小根堆所以我们可以将数字出现的次数添加一个负号这样相当于构建了一个大根堆,每一次都是可以拿取堆顶的次数出现次数最多的两个元素加入到结果集中,拿取元素可以使用heapq模块中的heappop方法这样可以保证拿取的元素是堆顶的两个元素,并且拿取元素之后字典中对应的次数需要减1,如果拿取了当前的元素之后字典中对应的次数还是大于0那么需要使用heapq模块中的heappush方法(维持堆的不变性)往元素堆中加入堆中(之前是弹出了对应的元素但是因为拿取之后次数还是大于0所以需要将其添加到结果集中),最后判断堆中是否还有元素假如还有元素将最后一个元素加入到结果集中,具体可以参考767题的博客
② 除了①中的方法之外,我们还可以根据数字出现的次数以间隔为2进行进行插入,所以可以使用字典来记录数字出现的次数,然后对字典进行排序得到按照出现次数由多到少排列的列表,这样就可以以间隔为2进行插入元素了
3. 代码如下:
大根堆:
import collections
import heapq
from typing import List
class Solution:
def rearrangeBarcodes(self, barcodes: List[int]) -> List[int]:
dic = collections.defaultdict(int)
for i in range(len(barcodes)):
dic[barcodes[i]] += 1
# 使用元组可以很方便地表示数字与对应出现次数的关系
queue = [(-x[1], x[0]) for x in dic.items()]
# print(queue)
# 将列表初始化为一个小根堆
heapq.heapify(queue)
res = list()
while len(queue) > 1:
# 弹出堆顶的两个元素
poll1 = heapq.heappop(queue)
poll2 = heapq.heappop(queue)
# 将弹出的元素加入到结果集中
res.append(poll1[1])
res.append(poll2[1])
# 字典的对应次数减1
dic[poll1[1]] -= 1
dic[poll2[1]] -= 1
# 因为之前将元素弹出列表了,所以当拿取元素之后出现次数还是大于0那么将元素加入到堆中
if dic[poll1[1]] > 0:
heapq.heappush(queue, (-dic[poll1[1]], poll1[1]))
if dic[poll2[1]] > 0:
heapq.heappush(queue, (-dic[poll2[1]], poll2[1]))
# 当元素的长度为奇数的时候那么最后肯定会剩下一个元素所以将最后一个元素加入到结果集中
if queue:
res.append(queue[0][1])
return res
间隔为2进行插入:
import collections
from typing import List
class Solution:
def rearrangeBarcodes(self, barcodes: List[int]) -> List[int]:
dic = collections.defaultdict(int)
for num in barcodes:
dic[num] += 1
nums_count = sorted(dic, key=lambda x:-dic[x])
barcodes = list()
for i in range(len(nums_count)):
barcodes += [nums_count[i]] * dic[nums_count[i]]
res = [None for i in range(len(barcodes))]
res[::2] = barcodes[:len(barcodes[::2])]
res[1::2] = barcodes[len(barcodes[::2]):]
return res