🧠
Optimized Greedy Using Max Heap (Priority Queue)
💡 Using a max heap to always pick the most frequent element available ensures no two adjacent elements are equal by alternating picks. This is like always choosing the two most common beads left to place next, ensuring spacing between identical beads.
Intuition
Always pick the two most frequent remaining elements and place them alternately to avoid adjacency of duplicates.
Algorithm
- Count frequency of each element.
- Push all elements with their frequencies into a max heap.
- Pop two most frequent elements and append them to the result.
- Decrease their counts and push back if still positive.
- Repeat until heap is empty or one element remains.
- If one element remains, check if its count is 1 and append it; else return empty.
💡 This approach ensures no two adjacent elements are equal by always alternating the most frequent elements.
from collections import Counter
import heapq
def make_array_beautiful_heap(arr):
freq = Counter(arr)
max_freq = max(freq.values())
n = len(arr)
if max_freq > (n + 1) // 2:
return []
heap = [(-count, num) for num, count in freq.items()]
heapq.heapify(heap)
res = []
prev_count, prev_num = 0, None
while heap:
count, num = heapq.heappop(heap)
res.append(num)
if prev_count < 0:
heapq.heappush(heap, (prev_count, prev_num))
prev_count, prev_num = count + 1, num
return res
# Driver code
if __name__ == '__main__':
arr = [1,1,2,2,3,3]
print(make_array_beautiful_heap(arr))
Line Notes
freq = Counter(arr)Count frequencies of elements
heap = [(-count, num) for num, count in freq.items()]Create max heap by negating counts
prev_count, prev_num = 0, NoneTrack previously used element to avoid adjacency
if prev_count < 0: heapq.heappush(heap, (prev_count, prev_num))Push back previous element if still available
import java.util.*;
public class MakeArrayBeautifulHeap {
public static int[] makeBeautiful(int[] arr) {
int n = arr.length;
Map<Integer, Integer> freq = new HashMap<>();
for (int num : arr) freq.put(num, freq.getOrDefault(num, 0) + 1);
int maxFreq = Collections.max(freq.values());
if (maxFreq > (n + 1) / 2) return new int[0];
PriorityQueue<int[]> maxHeap = new PriorityQueue<>((a, b) -> b[0] - a[0]);
for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
maxHeap.offer(new int[]{entry.getValue(), entry.getKey()});
}
int[] res = new int[n];
int idx = 0;
int[] prev = {0, 0};
while (!maxHeap.isEmpty()) {
int[] curr = maxHeap.poll();
res[idx++] = curr[1];
curr[0]--;
if (prev[0] > 0) maxHeap.offer(prev);
prev = curr;
}
if (idx != n) return new int[0];
return res;
}
public static void main(String[] args) {
int[] arr = {1,1,2,2,3,3};
System.out.println(Arrays.toString(makeBeautiful(arr)));
}
}
Line Notes
PriorityQueue<int[]> maxHeap = new PriorityQueue<>((a, b) -> b[0] - a[0])Max heap based on frequency
int[] prev = {0, 0};Track previously used element and its count
if (prev[0] > 0) maxHeap.offer(prev);Push back previous element if still available
if (idx != n) return new int[0];Check if all elements placed successfully
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std;
vector<int> makeBeautifulHeap(vector<int>& arr) {
int n = arr.size();
unordered_map<int, int> freq;
for (int x : arr) freq[x]++;
int maxFreq = 0;
for (auto& p : freq) maxFreq = max(maxFreq, p.second);
if (maxFreq > (n + 1) / 2) return {};
priority_queue<pair<int,int>> maxHeap;
for (auto& p : freq) maxHeap.push({p.second, p.first});
vector<int> res;
pair<int,int> prev = {0, 0};
while (!maxHeap.empty()) {
auto curr = maxHeap.top(); maxHeap.pop();
res.push_back(curr.second);
if (prev.first > 0) maxHeap.push(prev);
curr.first--;
prev = curr;
}
if ((int)res.size() != n) return {};
return res;
}
int main() {
vector<int> arr = {1,1,2,2,3,3};
vector<int> res = makeBeautifulHeap(arr);
if (res.empty()) cout << "[]" << endl;
else {
for (int x : res) cout << x << " ";
cout << endl;
}
return 0;
}
Line Notes
priority_queue<pair<int,int>> maxHeap;Max heap stores frequency and element
pair<int,int> prev = {0, 0};Track previously used element to avoid adjacency
if (prev.first > 0) maxHeap.push(prev);Push back previous element if still available
if ((int)res.size() != n) return {};Verify all elements placed successfully
function makeArrayBeautifulHeap(arr) {
const freq = new Map();
for (const num of arr) freq.set(num, (freq.get(num) || 0) + 1);
const n = arr.length;
let maxFreq = 0;
for (const count of freq.values()) maxFreq = Math.max(maxFreq, count);
if (maxFreq > Math.floor((n + 1) / 2)) return [];
const maxHeap = [];
for (const [num, count] of freq.entries()) {
maxHeap.push({num, count});
}
maxHeap.sort((a, b) => b.count - a.count);
const res = [];
let prev = null;
while (maxHeap.length > 0) {
let curr = maxHeap.shift();
res.push(curr.num);
if (prev !== null) {
maxHeap.push(prev);
maxHeap.sort((a, b) => b.count - a.count);
}
curr.count--;
prev = curr.count > 0 ? curr : null;
}
if (res.length !== n) return [];
return res;
}
// Test
console.log(makeArrayBeautifulHeap([1,1,2,2,3,3]));
Line Notes
const freq = new Map();Count frequencies of elements
if (maxFreq > Math.floor((n + 1) / 2)) return [];Check feasibility
maxHeap.sort((a, b) => b.count - a.count);Sort max heap by frequency descending
if (prev !== null) { maxHeap.push(prev); ... }Push back previously used element if still available
Counting frequencies is O(n), heap operations O(log k) per element, where k is distinct elements.
💡 For large n but small k, this approach is very efficient.
Interview Verdict: Accepted
This approach is optimal for large inputs and dynamic scenarios, demonstrating mastery of greedy and heap data structures.