Given a set of n nuts of different sizes and n bolts of different sizes. There is a one-one mapping between nuts and bolts. Match nuts and bolts efficiently. Comparison of a nut to another nut or a bolt to another bolt is not allowed. The elements in output should follow the following order: { !,#,$,%,&,*,?,@,^ }
Input: , nuts[] = {@, %, $, #, ^}, bolts[] = {%, @, #, $ ^}
Output: # $ % @ ^
Explanation: As per the order # should come first after that $ then % then @ and ^.Input: nuts[] = {^, &, %, @, #, *, $, ?, !}, bolts[] = {?, #, @, %, &, *, $ ,^, !}
Output: ! # $ % & * ? @ ^
Explanation: We'll have to match first ! then # , $, %, &, *, @, ^, ? as per the required ordering.
Using Quick Sort Partitioning - O(n log n) Time and O(log n) Space
Quick sort is applied on nuts and bolts simultaneously — the last bolt acts as a pivot to partition nuts, then the matched nut partitions bolts. This cross-partitioning repeats recursively on left and right sub-arrays until all pairs are matched.
Here how it works:
1. Pick the last element of bolts[] as pivot and partition the nuts[] array around it, returning index i.
2. Use nuts[i] as the next pivot to partition the bolts[] array. Each partition runs in O(n).
3. Recur on the left and right sub-arrays of both nuts[] and bolts[] until all pairs are matched.
#include <iostream>
#include <vector>
using namespace std;
// Partition function
int partition(vector<char> &arr, int low, int high, char pivot) {
int i = low;
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
swap(arr[i], arr[j]);
i++;
}
else if (arr[j] == pivot) {
swap(arr[j], arr[high]);
// recheck swapped element
j--;
}
}
swap(arr[i], arr[high]);
return i;
}
// Helper recursive function
void solve(vector<char> &nuts, vector<char> &bolts, int low, int high) {
if (low < high) {
int pivot = partition(nuts, low, high, bolts[high]);
partition(bolts, low, high, nuts[pivot]);
solve(nuts, bolts, low, pivot - 1);
solve(nuts, bolts, pivot + 1, high);
}
}
// Required function
void matchPairs(vector<char> &nuts, vector<char> &bolts) {
solve(nuts, bolts, 0, nuts.size() - 1);
}
// Driver code
int main() {
vector<char> nuts = {'@', '#', '$', '%', '^', '&'};
vector<char> bolts = {'$', '%', '&', '^', '@', '#'};
matchPairs(nuts, bolts);
for (char c : bolts) cout << c << " ";
return 0;
}
#include <stdio.h>
void swap(char *a, char *b) {
char temp = *a;
*a = *b;
*b = temp;
}
// Partition function (same logic as QuickSort)
int partition(char arr[], int low, int high, char pivot) {
int i = low;
for (int j = low; j < high; j++) {
// If element is smaller than pivot
if (arr[j] < pivot) {
swap(&arr[i], &arr[j]);
i++;
}
// If element equals pivot → move to end
else if (arr[j] == pivot) {
swap(&arr[j], &arr[high]);
j--; // recheck swapped element
}
}
// Place pivot at correct position
swap(&arr[i], &arr[high]);
return i;
}
// Recursive helper function
void solve(char nuts[], char bolts[], int low, int high) {
if (low < high) {
// Use last bolt as pivot for nuts
int pivot = partition(nuts, low, high, bolts[high]);
// Use matched nut as pivot for bolts
partition(bolts, low, high, nuts[pivot]);
// Recur for left and right parts
solve(nuts, bolts, low, pivot - 1);
solve(nuts, bolts, pivot + 1, high);
}
}
// Main function to match pairs
void matchPairs(char nuts[], char bolts[], int n) {
solve(nuts, bolts, 0, n - 1);
}
// Driver code
int main() {
char nuts[] = {'@', '#', '$', '%', '^', '&'};
char bolts[] = {'$', '%', '&', '^', '@', '#'};
int n = sizeof(nuts) / sizeof(nuts[0]);
matchPairs(nuts, bolts, n);
// Print result
for (int i = 0; i < n; i++) {
printf("%c ", bolts[i]);
}
return 0;
}
import java.util.*;
class GFG {
// Partition function similar to quicksort
static int partition(char[] arr, int low, int high, char pivot) {
int i = low;
for (int j = low; j < high; j++) {
// If current element is smaller than pivot
if (arr[j] < pivot) {
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
// If element equals pivot → move it to end
else if (arr[j] == pivot) {
char temp = arr[j];
arr[j] = arr[high];
arr[high] = temp;
j--; // recheck swapped element
}
}
// Place pivot at correct position
char temp = arr[i];
arr[i] = arr[high];
arr[high] = temp;
return i;
}
// Recursive helper
static void solve(char[] nuts, char[] bolts, int low, int high) {
if (low < high) {
// Use last bolt as pivot for nuts
int pivot = partition(nuts, low, high, bolts[high]);
// Use matched nut as pivot for bolts
partition(bolts, low, high, nuts[pivot]);
// Recur left and right
solve(nuts, bolts, low, pivot - 1);
solve(nuts, bolts, pivot + 1, high);
}
}
static void matchPairs(char[] nuts, char[] bolts) {
solve(nuts, bolts, 0, nuts.length - 1);
}
public static void main(String[] args) {
char[] nuts = {'@', '#', '$', '%', '^', '&'};
char[] bolts = {'$', '%', '&', '^', '@', '#'};
matchPairs(nuts, bolts);
for (char c : bolts) {
System.out.print(c + " ");
}
}
}
# Partition function
def partition(arr, low, high, pivot):
i = low
j = low
while j < high:
if arr[j] < pivot:
arr[i], arr[j] = arr[j], arr[i]
i += 1
j += 1
elif arr[j] == pivot:
arr[j], arr[high] = arr[high], arr[j]
# Do not increment j.
# Recheck the newly swapped element.
else:
j += 1
arr[i], arr[high] = arr[high], arr[i]
return i
# Helper recursive function
def solve(nuts, bolts, low, high):
if low >= high:
return
# Use a bolt as pivot to partition nuts
pivot = partition(nuts, low, high, bolts[high])
# Use the matched nut as pivot to partition bolts
partition(bolts, low, high, nuts[pivot])
solve(nuts, bolts, low, pivot - 1)
solve(nuts, bolts, pivot + 1, high)
# Required function
def matchPairs(nuts, bolts):
solve(nuts, bolts, 0, len(nuts) - 1)
# Driver code
nuts = ['@', '#', '$', '%', '^', '&']
bolts = ['$', '%', '&', '^', '@', '#']
matchPairs(nuts, bolts)
for c in bolts:
print(c, end=" ")
using System;
class GFG {
// Partition function
static int Partition(char[] arr, int low, int high, char pivot) {
int i = low;
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
else if (arr[j] == pivot) {
char temp = arr[j];
arr[j] = arr[high];
arr[high] = temp;
j--; // recheck
}
}
char t = arr[i];
arr[i] = arr[high];
arr[high] = t;
return i;
}
// Recursive function
static void Solve(char[] nuts, char[] bolts, int low, int high) {
if (low < high) {
int pivot = Partition(nuts, low, high, bolts[high]);
Partition(bolts, low, high, nuts[pivot]);
Solve(nuts, bolts, low, pivot - 1);
Solve(nuts, bolts, pivot + 1, high);
}
}
static void matchPairs(char[] nuts, char[] bolts) {
Solve(nuts, bolts, 0, nuts.Length - 1);
}
static void Main() {
char[] nuts = { '@', '#', '$', '%', '^', '&' };
char[] bolts = { '$', '%', '&', '^', '@', '#' };
matchPairs(nuts, bolts);
foreach (char c in bolts) {
Console.Write(c + " ");
}
}
}
// Partition function
function partition(arr, low, high, pivot) {
let i = low;
for (let j = low; j < high; j++) {
// Smaller than pivot
if (arr[j] < pivot) {
[arr[i], arr[j]] = [arr[j], arr[i]];
i++;
}
// Equal to pivot → move to end
else if (arr[j] === pivot) {
[arr[j], arr[high]] = [arr[high], arr[j]];
j--; // recheck
}
}
// Place pivot correctly
[arr[i], arr[high]] = [arr[high], arr[i]];
return i;
}
// Recursive helper
function solve(nuts, bolts, low, high) {
if (low < high) {
let pivot = partition(nuts, low, high, bolts[high]);
partition(bolts, low, high, nuts[pivot]);
solve(nuts, bolts, low, pivot - 1);
solve(nuts, bolts, pivot + 1, high);
}
}
// Main function
function matchPairs(nuts, bolts) {
solve(nuts, bolts, 0, nuts.length - 1);
}
// Driver
let nuts = ['@', '#', '$', '%', '^', '&'];
let bolts = ['$', '%', '&', '^', '@', '#'];
matchPairs(nuts, bolts);
console.log(bolts.join(" "));
Output
# $ % & @ ^
Why we cannot use Hashing to solve this ?
If we use hashing, then we will have to compare nuts with nuts or bolts with bolts either while inserting into the hash and/or while printing the result in sorted order.