Given two integer arrays a1[] and a2[]. Sort the first array a1[] such that all the relative positions of the elements in the first array are the same as the elements in the second array a2[].
Note: If elements are repeated in the second array, consider their first occurance only. Elements not in a2[] should appear in a1[] at the end in ascending order.
Example:
Input: a1 = [2, 1, 2, 3, 4], a2 = [2, 1, 2]
Output: [2, 2, 1, 3, 4]
Explanation: Array elements of a1[] are sorted according to a2[]. So 2 comes first then 1 comes, now we append remaining elements of a1[] in sorted order.Input: a1 = [4, 1, 3, 3, 2], a2 = [3, 1]
Output: [3, 3, 1, 2, 4]
Explanation: Elements 3 and 1 come first as per a2. Others (2, 4) are sorted and placed after.
Table of Content
Hashing - O(m*log m + n) Time and O(m) Space
First, count how many times each number appears in a1[] using a map. Then, follow the order of a2[] and place all occurrences of each number into a1[]. Finally, sort the numbers that are left and place them at the end.
Consider a1[] = [2, 1, 2, 3, 4] and a2[] = [2, 1, 2].
Step 1: Count the frequency of each element in a1[].
The map becomes {2: 2, 1: 1, 3: 1, 4: 1} because 2 appears twice, while 1, 3, and 4 appear once.
Step 2: Traverse a2[] and place its elements first.
- The first element is 2. Its frequency is 2, so place both occurrences of 2 in a1[]. Result: [2, 2].
- The next element is 1. Its frequency is 1, so place it next. Result: [2, 2, 1].
- The last element is 2 again, but it has already been processed, so skip it.
Step 3: Place the remaining elements.
- The remaining elements are 3 and 4.
- Sort them in ascending order and append them to the result.
Final array: [2, 2, 1, 3, 4]
#include<iostream>
#include<vector>
#include<unordered_map>
#include<algorithm>
using namespace std;
void relativeSort(vector<int>& a1, vector<int>& a2){
int m = a1.size(), n = a2.size();
unordered_map<int, int> freq;
// Count frequency of each element in a1
for (int i = 0; i < m; i++) {
freq[a1[i]]++;
}
int index = 0;
// Place elements of a2 in a1 based on frequency
for (int i = 0; i < n; i++) {
while (freq[a2[i]]) {
a1[index++] = a2[i];
freq[a2[i]]--;
}
freq.erase(a2[i]);
}
// Collect remaining elements and sort them
vector<int> remaining;
for (auto& pair : freq) {
while (pair.second--) {
remaining.push_back(pair.first);
}
}
sort(remaining.begin(), remaining.end());
// Append remaining elements to a1
for (int i : remaining) {
a1[index++] = i;
}
}
int main(){
vector<int> a1 = { 2, 1, 2, 3, 4};
vector<int> a2 = { 2, 1, 2 };
relativeSort(a1, a2);
for (int i = 0; i < a1.size(); i++) {
cout << a1[i] << " ";
}
cout << endl;
return 0;
}
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
class GFG {
static void relativeSort(int[] a1, int[] a2) {
int m = a1.length, n = a2.length;
Map<Integer, Integer> freq = new HashMap<>();
// Count frequency of each element in a1
for (int i = 0; i < m; i++) {
freq.put(a1[i], freq.getOrDefault(a1[i], 0) + 1);
}
int index = 0;
// Place elements of a2 in a1 based on frequency
for (int i = 0; i < n; i++) {
while (freq.getOrDefault(a2[i], 0) > 0) {
a1[index++] = a2[i];
freq.put(a2[i], freq.get(a2[i]) - 1);
}
freq.remove(a2[i]);
}
// Collect remaining elements and sort them
List<Integer> remaining = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
for (int i = 0; i < entry.getValue(); i++) {
remaining.add(entry.getKey());
}
}
Collections.sort(remaining);
// Append remaining elements to a1
for (int num : remaining) {
a1[index++] = num;
}
}
public static void main(String[] args) {
int[] a1 = {2, 1, 2, 3, 4};
int[] a2 = {2, 1, 2};
relativeSort(a1, a2);
for (int num : a1) {
System.out.print(num + " ");
}
System.out.println();
}
}
def relativeSort(a1, a2):
m, n = len(a1), len(a2)
freq = {}
# Count frequency of each element in a1
for num in a1:
freq[num] = freq.get(num, 0) + 1
index = 0
# Place elements of a2 in a1 based on frequency
for num in a2:
while freq.get(num, 0) > 0:
a1[index] = num
index += 1
freq[num] -= 1
freq.pop(num, None)
# Collect remaining elements and sort them
remaining = []
for key in freq:
remaining.extend([key] * freq[key])
remaining.sort()
# Append remaining elements to a1
for num in remaining:
a1[index] = num
index += 1
if __name__ == "__main__":
a1 = [2, 1, 2, 3, 4]
a2 = [2, 1, 2]
relativeSort(a1, a2)
for num in a1:
print(num, end=" ")
print()
using System;
using System.Collections.Generic;
class GFG {
static void relativeSort(int[] a1, int[] a2) {
int m = a1.Length, n = a2.Length;
Dictionary<int, int> freq = new Dictionary<int, int>();
// Count frequency of each element in a1
for (int i = 0; i < m; i++) {
if (!freq.ContainsKey(a1[i])) {
freq[a1[i]] = 0;
}
freq[a1[i]]++;
}
int index = 0;
// Place elements of a2 in a1 based on frequency
for (int i = 0; i < n; i++) {
// Safely check if a2[i] exists and its frequency is greater than 0
while (freq.ContainsKey(a2[i]) && freq[a2[i]] > 0) {
a1[index++] = a2[i];
freq[a2[i]]--;
}
// Remove the key just like Java's freq.remove(a2[i])
if (freq.ContainsKey(a2[i])) {
freq.Remove(a2[i]);
}
}
// Collect remaining elements and sort them
List<int> remaining = new List<int>();
foreach (KeyValuePair<int, int> entry in freq) {
for (int i = 0; i < entry.Value; i++) {
remaining.Add(entry.Key);
}
}
remaining.Sort();
// Append remaining elements to a1
foreach (int num in remaining) {
a1[index++] = num;
}
}
public static void Main(string[] args) {
int[] a1 = {2, 1, 2, 3, 4};
int[] a2 = {2, 1, 2};
relativeSort(a1, a2);
foreach (int num in a1) {
Console.Write(num + " ");
}
Console.WriteLine();
}
}
function relativeSort(a1, a2) {
let m = a1.length, n = a2.length;
let freq = new Map();
// Count frequency of each element in a1
for (let i = 0; i < m; i++) {
freq.set(a1[i], (freq.get(a1[i]) || 0) + 1);
}
let index = 0;
// Place elements of a2 in a1 based on frequency
for (let i = 0; i < n; i++) {
while (freq.get(a2[i]) > 0) {
a1[index++] = a2[i];
freq.set(a2[i], freq.get(a2[i]) - 1);
}
freq.delete(a2[i]);
}
// Collect remaining elements and sort them
let remaining = [];
for (let [key, val] of freq.entries()) {
while (val--) remaining.push(key);
}
remaining.sort((a, b) => a - b);
// Append remaining elements to a1
for (let i = 0; i < remaining.length; i++) {
a1[index++] = remaining[i];
}
}
// Driver Code
let a1 = [2, 1, 2, 3, 4];
let a2 = [2, 1, 2];
relativeSort(a1, a2);
console.log(a1.join(" "));
Output
2 2 1 3 4
Custom Comparator - O(m*log m + n) Time and O(n) Space
The idea is to sort the first array a1[] based on the relative order of elements defined in the second array a2[].
A hash map stores the index of each element in a2[] to define their priority.
While sorting a1[], a custom comparator uses this map to ensure that elements present in a2[] come first in the correct order, and the rest are sorted naturally in increasing order.
- Traverse a2[] and store the index of each element in a hash map to define custom order.
- Sort a1[] using a lambda comparator with the help of the map.
- If both elements are in the map, compare their positions from the map.
- If only one is in the map, prioritize it over the one that is not.
- If neither is in the map, sort them in increasing numerical order.
- The final a1[] follows the order of a2[] for common elements and sorts the rest normally.
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
void relativeSort(vector<int>& a1, vector<int>& a2) {
// create a map to store the index of
// each element in a2
unordered_map<int, int> mp;
for (int i = 0; i < a2.size(); i++) {
if (mp.count(a2[i]) == 0)
mp[a2[i]] = i;
}
// custom comparator using lambda
sort(a1.begin(), a1.end(), [&](int a, int b) {
bool aIn = mp.count(a), bIn = mp.count(b);
if (!aIn && !bIn) return a < b;
if (!aIn) return false;
if (!bIn) return true;
return mp[a] < mp[b];
});
}
int main() {
vector<int> a1 = {2, 1, 2, 3, 4};
vector<int> a2 = {2, 1, 2};
relativeSort(a1, a2);
for (int x : a1)
cout << x << " ";
cout << endl;
return 0;
}
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
class GFG {
static void relativeSort(int[] a1, int[] a2) {
// Create a map to store the index of each
// element in a2
Map<Integer, Integer> mp = new HashMap<>();
for (int i = 0; i < a2.length; i++) {
if (!mp.containsKey(a2[i]))
mp.put(a2[i], i);
}
// Convert int[] to Integer[] for custom sorting
Integer[] temp = Arrays.stream(a1).boxed().toArray(Integer[]::new);
// Custom comparator using lambda
Arrays.sort(temp, (a, b) -> {
boolean aIn = mp.containsKey(a), bIn = mp.containsKey(b);
if (!aIn && !bIn) return Integer.compare(a, b);
if (!aIn) return 1;
if (!bIn) return -1;
return Integer.compare(mp.get(a), mp.get(b));
});
// Copy sorted values back to original array
for (int i = 0; i < a1.length; i++) {
a1[i] = temp[i];
}
}
public static void main(String[] args) {
int[] a1 = {2, 1, 2, 3, 4};
int[] a2 = {2, 1, 2};
relativeSort(a1, a2);
for (int num : a1)
System.out.print(num + " ");
System.out.println();
}
}
def relativeSort(a1, a2):
# create a map to store the index of each element in a2
mp = {}
for i in range(len(a2)):
if a2[i] not in mp:
mp[a2[i]] = i
# custom comparator using lambda inside sort's key
a1.sort(key=lambda x: (mp.get(x, float('inf')), x))
if __name__ == "__main__":
a1 = [2, 1, 2, 3, 4]
a2 = [2, 1, 2]
relativeSort(a1, a2)
for x in a1:
print(x, end=" ")
print()
using System;
using System.Collections.Generic;
class GFG {
static void relativeSort(int[] a1, int[] a2) {
// Create a map to store the index of each element in a2
Dictionary<int, int> mp = new Dictionary<int, int>();
for (int i = 0; i < a2.Length; i++) {
if (!mp.ContainsKey(a2[i]))
mp[a2[i]] = i;
}
// Custom comparator using lambda
Array.Sort(a1, (a, b) => {
bool aIn = mp.ContainsKey(a), bIn = mp.ContainsKey(b);
if (!aIn && !bIn) return a.CompareTo(b);
if (!aIn) return 1;
if (!bIn) return -1;
return mp[a].CompareTo(mp[b]);
});
}
public static void Main() {
int[] a1 = {2, 1, 2, 3, 4};
int[] a2 = {2, 1, 2};
relativeSort(a1, a2);
foreach (int x in a1)
Console.Write(x + " ");
Console.WriteLine();
}
}
function relativeSort(a1, a2) {
// Create a map to store the index of
// each element in a2
let mp = new Map();
for (let i = 0; i < a2.length; i++) {
if (!mp.has(a2[i])) {
mp.set(a2[i], i);
}
}
// Custom comparator using lambda
a1.sort((a, b) => {
let aIn = mp.has(a), bIn = mp.has(b);
if (!aIn && !bIn) return a - b;
if (!aIn) return 1;
if (!bIn) return -1;
return mp.get(a) - mp.get(b);
});
}
// Driver Code
let a1 = [2, 1, 2, 3, 4];
let a2 = [2, 1, 2];
relativeSort(a1, a2);
console.log(a1.join(" "));
Output
2 2 1 3 4