Given two arrays a[] and b[] of size n (each containing distinct integers, but possibly sharing some), construct an array res[] of size n that contains the largest n unique values from both arrays combined, where elements taken from a[] appear first in their original order, followed by elements from b[] in their original order, and no value appears more than once.
Examples:
Input: a[] = [9, 7, 2, 3, 6], b[] = [7, 4, 8, 0, 1]
Output: [9, 7, 6, 4, 8]
Explanation:
Largest 5 unique elements from both arrays: {9, 8, 7, 6, 4}.
From a[], take elements in order that are in top 5: 9, 7, 6.
From b[], take remaining top elements: 4, 8.
Resulting array: [9, 7, 6, 4, 8].Input: a[] = [6, 7, 5, 3], b[] = [5, 6, 2, 9]
Output: [6, 7, 5, 9]
Explanation:
Largest 4 unique elements from both arrays: {9, 7, 6, 5}.
From a[], take elements in order: 6, 7, 5.
From b[], add remaining top element: 9.
Resulting array: [6, 7, 5, 9].
[Approach] Using Set - O(n log(n)) Time and O(n) Space
We can use a set (or similar data structure) that always maintains the n largest unique elements while scanning both arrays. As we insert elements from a[] and then b[], remove the smallest whenever the set size exceeds n. After processing both arrays, this set represents the final chosen values.
To build the result, traverse a[] first and pick the elements that appear in the set, then traverse b[] for the remaining ones. This keeps the largest possible n values and preserves the required order: elements from a[] first, followed by elements from b[].
//Driver Code Starts
#include <iostream>
#include <set>
#include <vector>
using namespace std;
//Driver Code Ends
vector<int> makelargest(vector<int> &a, vector<int> &b) {
int n = a.size();
set<int> se;
// insert from a and keep only largest n elements
for (int i = 0; i < n; i++) {
se.insert(a[i]);
if (se.size() > n) se.erase(se.begin());
}
// insert from b and keep only largest n elements
for (int i = 0; i < n; i++) {
se.insert(b[i]);
if (se.size() > n) se.erase(se.begin());
}
vector<int> ans;
// pick elements from a in original order
for (int i = 0; i < n; i++) {
auto it = se.find(a[i]);
if (it != se.end()) {
ans.push_back(a[i]);
se.erase(it);
}
}
// pick elements from b in original order
for (int i = 0; i < n; i++) {
auto it = se.find(b[i]);
if (it != se.end()) {
ans.push_back(b[i]);
se.erase(it);
}
}
return ans;
}
//Driver Code Starts
int main() {
vector<int> a = {9, 7, 2, 3, 6};
vector<int> b = {7, 4, 8, 0, 1};
vector<int> ans = makelargest(a, b);
for (int x : ans) cout << x << " ";
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
import java.util.TreeSet;
class GFG {
//Driver Code Ends
static ArrayList<Integer> makelargest(int[] a, int[] b) {
int n = a.length;
TreeSet<Integer> se = new TreeSet<>();
// insert from a and keep largest n
for (int i = 0; i < n; i++) {
se.add(a[i]);
if (se.size() > n) se.pollFirst();
}
// insert from b and keep largest n
for (int i = 0; i < n; i++) {
se.add(b[i]);
if (se.size() > n) se.pollFirst();
}
ArrayList<Integer> ans = new ArrayList<>();
// pick elements from a in original order
for (int i = 0; i < n; i++) {
if (se.contains(a[i])) {
ans.add(a[i]);
se.remove(a[i]);
}
}
// pick elements from b in original order
for (int i = 0; i < n; i++) {
if (se.contains(b[i])) {
ans.add(b[i]);
se.remove(b[i]);
}
}
return ans;
}
//Driver Code Starts
public static void main(String[] args) {
int[] a = {9, 7, 2, 3, 6};
int[] b = {7, 4, 8, 0, 1};
ArrayList<Integer> ans = makelargest(a, b);
for (int x : ans) System.out.print(x + " ");
}
}
//Driver Code Ends
def makelargest(a, b):
n = len(a)
se = set()
# insert elements from a and keep only the largest n
for i in range(n):
se.add(a[i])
if len(se) > n:
se.remove(min(se))
# insert elements from b and keep only the largest n
for i in range(n):
se.add(b[i])
if len(se) > n:
se.remove(min(se))
ans = []
# pick remaining elements from a, in original order
for i in range(n):
if a[i] in se:
ans.append(a[i])
se.remove(a[i])
# pick remaining elements from b, in original order
for i in range(n):
if b[i] in se:
ans.append(b[i])
se.remove(b[i])
return ans
#Driver Code Starts
if __name__ == "__main__":
a = [9, 7, 2, 3, 6]
b = [7, 4, 8, 0, 1]
ans = makelargest(a, b)
for x in ans:
print(x, end=" ")
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GFG {
//Driver Code Ends
static List<int> makelargest(int[] a, int[] b) {
int n = a.Length;
SortedSet<int> se = new SortedSet<int>();
// insert elements from a and keep only the largest n
for (int i = 0; i < n; i++) {
se.Add(a[i]);
if (se.Count > n) se.Remove(se.Min);
}
// insert elements from b and keep only the largest n
for (int i = 0; i < n; i++) {
se.Add(b[i]);
if (se.Count > n) se.Remove(se.Min);
}
List<int> ans = new List<int>();
// pick remaining elements from a in order
for (int i = 0; i < n; i++) {
if (se.Contains(a[i])) {
ans.Add(a[i]);
se.Remove(a[i]);
}
}
// pick remaining elements from b in order
for (int i = 0; i < n; i++) {
if (se.Contains(b[i])) {
ans.Add(b[i]);
se.Remove(b[i]);
}
}
return ans;
}
//Driver Code Starts
static void Main() {
int[] a = {9, 7, 2, 3, 6};
int[] b = {7, 4, 8, 0, 1};
List<int> ans = makelargest(a, b);
foreach (int x in ans) Console.Write(x + " ");
}
}
//Driver Code Ends
//Driver Code Starts
class MinHeap {
constructor() { this.h = []; }
push(x) {
this.h.push(x);
this._up(this.h.length - 1);
}
pop() {
if (this.h.length === 0) return null;
const top = this.h[0];
const last = this.h.pop();
if (this.h.length > 0) {
this.h[0] = last;
this._down(0);
}
return top;
}
top() { return this.h.length ? this.h[0] : null; }
size() { return this.h.length; }
_up(i) {
while (i > 0) {
const p = Math.floor((i - 1) / 2);
if (this.h[p] <= this.h[i]) break;
[this.h[p], this.h[i]] = [this.h[i], this.h[p]];
i = p;
}
}
_down(i) {
const n = this.h.length;
while (true) {
const l = 2 * i + 1, r = 2 * i + 2;
let smallest = i;
if (l < n && this.h[l] < this.h[smallest]) smallest = l;
if (r < n && this.h[r] < this.h[smallest]) smallest = r;
if (smallest === i) break;
[this.h[i], this.h[smallest]] = [this.h[smallest], this.h[i]];
i = smallest;
}
}
}
//Driver Code Ends
// insert unique value into heap+present (if not present already)
// and ensure heap size <= limit by popping smallest when needed
function insertUnique(x, heap, present, limit) {
if (present.has(x)) return;
heap.push(x);
present.add(x);
if (heap.size() > limit) {
const mn = heap.pop();
// mn must be in present (we only inserted unique values)
present.delete(mn);
}
}
// build result by scanning arr, picking present values in order
function collectInOrder(arr, present, out) {
for (const x of arr) {
if (present.has(x)) {
out.push(x);
present.delete(x);
}
}
}
function makelargest(a, b) {
const n = a.length;
const heap = new MinHeap();
const present = new Set();
// insert unique from a, keeping only largest n
for (const x of a) insertUnique(x, heap, present, n);
// insert unique from b, keeping only largest n
for (const x of b) insertUnique(x, heap, present, n);
// present now holds the top n unique values
const ans = [];
collectInOrder(a, present, ans);
collectInOrder(b, present, ans);
return ans;
}
//Driver Code Starts
// Driver Code
const a = [9, 7, 2, 3, 6];
const b = [7, 4, 8, 0, 1];
console.log(makelargest(a, b).join(' '));
//Driver Code Ends
Output
9 7 6 4 8