from collections import Counter
import heapq
class Solution:
def rearrangeBarcodes(self, barcodes):
count = Counter(barcodes)
# Max heap: (-freq, barcode)
heap = [(-freq, num) for num, freq in count.items()]
heapq.heapify(heap)
res = []
prev_freq, prev_num = 0, None
while heap:
freq, num = heapq.heappop(heap)
res.append(num)
# If previous barcode still has count, push it back
if prev_freq < 0:
heapq.heappush(heap, (prev_freq, prev_num))
# Prepare for next round
prev_freq, prev_num = freq + 1, num # decrease freq
return res
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;
class Solution {
public:
vector<int> rearrangeBarcodes(vector<int>& barcodes) {
unordered_map<int, int> count;
for (int b : barcodes) count[b]++;
// Max heap: pair<freq, barcode>
priority_queue<pair<int, int>> heap;
for (auto &p : count) heap.push({p.second, p.first});
vector<int> res;
pair<int, int> prev = {0, 0};
while (!heap.empty()) {
auto cur = heap.top(); heap.pop();
res.push_back(cur.second);
if (prev.first > 0) heap.push(prev);
cur.first--;
prev = cur;
}
return res;
}
};
import java.util.*;
class Solution {
public int[] rearrangeBarcodes(int[] barcodes) {
Map<Integer, Integer> count = new HashMap<>();
for (int b : barcodes) count.put(b, count.getOrDefault(b, 0) + 1);
PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> b[0] - a[0]);
for (Map.Entry<Integer, Integer> entry : count.entrySet())
heap.add(new int[]{entry.getValue(), entry.getKey()});
int n = barcodes.length;
int[] res = new int[n];
int idx = 0;
int[] prev = new int[]{0, 0};
while (!heap.isEmpty()) {
int[] cur = heap.poll();
res[idx++] = cur[1];
if (prev[0] > 0) heap.add(prev);
cur[0]--;
prev = cur;
}
return res;
}
}
/**
* @param {number[]} barcodes
* @return {number[]}
*/
var rearrangeBarcodes = function(barcodes) {
const count = {};
for (let b of barcodes) count[b] = (count[b] || 0) + 1;
// Max heap using array and sort
let heap = Object.entries(count).map(([num, freq]) => [parseInt(freq), parseInt(num)]);
heap.sort((a, b) => b[0] - a[0]);
const res = [];
let prev = [0, 0];
while (heap.length) {
let cur = heap.shift();
res.push(cur[1]);
if (prev[0] > 0) heap.push(prev);
cur[0]--;
prev = cur;
heap.sort((a, b) => b[0] - a[0]);
}
return res;
};
You are given an array of integers called barcodes
, where each integer represents a barcode type. Your task is to rearrange the elements in barcodes
such that no two adjacent elements are the same. You must use every element exactly once, and it is guaranteed that at least one valid arrangement exists for the given input.
barcodes
(an array of integers)At first glance, the problem might look like a permutation or backtracking problem, where we try all possible arrangements and check if any two adjacent elements are the same. However, this would be very inefficient, especially for large inputs.
By observing the problem, we realize that the main challenge is to distribute the most frequent barcodes as evenly as possible to avoid having them adjacent. If we always place the most frequent barcode next to a different one, we can avoid adjacent duplicates.
This leads us to consider using a greedy approach: always pick the barcode with the highest remaining count, but never place the same barcode as the previous one.
To efficiently get the most frequent barcode at each step, we can use a max-heap (priority queue). Each time, we pick the most frequent barcode that is different from the last placed one. If we just used a regular queue or array, finding the max each time would be slow.
The solution uses a greedy algorithm with a max-heap (priority queue) to always place the most frequent available barcode, ensuring no two adjacent elements are the same.
This approach guarantees that no two adjacent barcodes are the same, and it uses every element exactly once.
Let's consider the input barcodes = [1,1,1,2,2,3]
.
n
.The Distant Barcodes problem is efficiently solved by using a greedy approach with a max-heap. By always choosing the most frequent barcode that is not the same as the previous one, we avoid adjacent duplicates and ensure all elements are used. This method is both elegant and efficient, avoiding the need for brute-force permutation checks and leveraging priority queues for optimal selection at each step.