1054. 距离相等的条形码
难度:中等
时间:2023/05/29
在一个仓库里,有一排条形码,其中第 i 个条形码为 barcodes[i]。
请你重新排列这些条形码,使其中任意两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案,此题保证存在答案。
示例 1:
输入:barcodes = [1,1,1,2,2,2]
输出:[2,1,2,1,2,1]
示例 2:
输入:barcodes = [1,1,1,1,2,2,3,3]
输出:[1,3,1,3,2,1,2,1]
提示:
1 <= barcodes.length <= 100001 <= barcodes[i] <= 10000
解题思路1:排序 + 分组
- 使用哈希表或者桶计数统计
barcodes中每个数出现的次数。 - 按照出现次数从大到小排序(注意次数相同的情况下,相同的情况下,按照数字本身递增或者递减排序都可以)。
- 遍历
barcodes数组,将答案先填入ret数组的偶数位置。 - 再遍历
barcodes数组,再将答案填入ret数组的奇数位置。
- Python
class Solution:
def rearrangeBarcodes(self, barcodes: List[int]) -> List[int]:
cnt = Counter(barcodes)
barcodes.sort(key=lambda x: (cnt[x], x), reverse=True)
n = len(barcodes)
ret = [0] * len(barcodes)
ret[::2] = barcodes[: (n + 1) // 2]
ret[1::2] = barcodes[(n + 1) // 2:]
return ret
- C++
class Solution {
public:
vector<int> rearrangeBarcodes(vector<int>& barcodes) {
auto mx = *max_element(barcodes.begin(), barcodes.end());
vector<int> cnt(mx + 1);
for (auto b : barcodes) {
cnt[b] += 1;
}
sort(barcodes.begin(), barcodes.end(), [&](auto x, auto y){
return cnt[x] > cnt[y] || (cnt[x] == cnt[y] && x > y);
});
auto n = barcodes.size();
vector<int> ret(n);
for (int k = 0, j = 0; k < 2; ++k) {
for (int i = k; i < n; i += 2) {
ret[i] = barcodes[j++];
}
}
return ret;
}
};
解题思路2:最大堆
-
先记录每个数字出现的次数,再以 (次数,数字) 的形式存入大根堆中,每次弹出次数最大的元素,与结果数组的最后一个值做比较;
- 如果相等继续弹出次数次大的元素加入结果,再将最大次数的数字加入结果
- 如果不相等直接将次数最大的元素加入结果
-
然后次数减一,判断剩余次数是否为 00, 为 00 则不再入堆,否则次数减一再次入堆。
class Solution {
public:
vector<int> rearrangeBarcodes(vector<int>& barcodes) {
unordered_map<int, int> rec;
for (int i : barcodes) ++rec[i];
priority_queue<pair<int, int>> pq;
for (auto it : rec) pq.push({it.second, it.first});
vector<int> ans;
while (!pq.empty()) {
auto [cnt, barcode] = pq.top(); pq.pop();
ans.push_back(barcode);
int cnt2, barcode2;
if (!pq.empty()) {
cnt2 = pq.top().first;
barcode2 = pq.top().second;
pq.pop();
ans.push_back(barcode2);
if (cnt2 > 1) pq.push({cnt2 - 1, barcode2});
}
if (cnt > 1) pq.push({cnt - 1, barcode});
}
return ans;
}
};