Given three sorted arrays a[], b[], and c[], choose one element from each array a[i], b[j], c[k] to minimize:
max(|a[i] − b[j]|, |b[j] − c[k]|, |c[k] − a[i]|), where |x| denotes the absolute value of x.
Find the chosen elements in order: a[i] b[j] c[k]. If multiple triplets give the same minimum value, return any of them.
Example :
Input : a[] = [1, 4, 10], b[] = [2, 15, 20], c[] = [10, 12]
Output: [10, 15, 10]
Explanation: Choosing 10 from a[], 15 from b[], and 10 from c[] gives max(|10-15|, |15-10|, |10-10|) = max(5, 5, 0) = 5, which is the minimum possible.Input: a[] = [20, 24, 100], b[] = [2, 19, 22, 79, 800], c[] = [10, 12, 23, 24, 119]
Output: [24, 22, 23]
Explanation: Choosing 24 from a[], 22 from b[], and 23 from c[] gives max(|24-22|, |22-23|, |23-24|) = max(2, 1, 1) = 2, which is the minimum possible.
Table of Content
[Naive Approach] Checking each triplet of elements - O(n1*n2*n3) Time and O(1) Space
The simplest approach is to try every possible combination of one element from each array. For each combination, we calculate the three differences between the chosen elements and take the maximum of these differences. Among all combinations, the one that gives the smallest maximum difference is the answer, and the corresponding elements from the arrays are the triplet we choose.
//Driver Code Starts
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
//Driver Code Ends
vector<int> findCloset(vector<int>& a, vector<int>& b, vector<int>& c) {
int n1 = a.size();
int n2 = b.size();
int n3 = c.size();
int minval = INT_MAX;
int ansA = 0, ansB = 0, ansC = 0;
// try all triplets
for(int i = 0; i < n1; i++) {
for(int j = 0; j < n2; j++) {
for(int k = 0; k < n3; k++) {
int val = max({abs(a[i]-b[j]),
abs(b[j]-c[k]), abs(c[k]-a[i])});
if(val < minval) {
minval = val;
ansA = a[i];
ansB = b[j];
ansC = c[k];
}
}
}
}
return {ansA, ansB, ansC};
}
//Driver Code Starts
int main() {
vector<int> a = {1, 4, 10};
vector<int> b = {2, 15, 20};
vector<int> c = {10, 12};
vector<int> ans = findCloset(a, b, c);
for(int x : ans) cout << x << " ";
cout << endl;
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
import java.util.Arrays;
class GFG {
//Driver Code Ends
static ArrayList<Integer> findCloset(int[] a, int[] b, int[] c) {
int n1 = a.length, n2 = b.length, n3 = c.length;
int minval = Integer.MAX_VALUE;
int ansA = 0, ansB = 0, ansC = 0;
// try all triplets
for(int i = 0; i < n1; i++) {
for(int j = 0; j < n2; j++) {
for(int k = 0; k < n3; k++) {
int val = Math.max(Math.abs(a[i]-b[j]),
Math.max(Math.abs(b[j]-c[k]),
Math.abs(c[k]-a[i])));
if(val < minval) {
minval = val;
ansA = a[i];
ansB = b[j];
ansC = c[k];
}
}
}
}
return new ArrayList<>(Arrays.asList(ansA, ansB, ansC));
}
//Driver Code Starts
public static void main(String[] args) {
int[] a = {1, 4, 10};
int[] b = {2, 15, 20};
int[] c = {10, 12};
ArrayList<Integer> ans = findCloset(a, b, c);
for(int x : ans) System.out.print(x + " ");
System.out.println();
}
}
//Driver Code Ends
def findCloset(a, b, c):
n1, n2, n3 = len(a), len(b), len(c)
minval = float('inf')
ansA = ansB = ansC = 0
# try all triplets
for i in range(n1):
for j in range(n2):
for k in range(n3):
val = max(abs(a[i]-b[j]), abs(b[j]-c[k]), abs(c[k]-a[i]))
if val < minval:
minval = val
ansA = a[i]
ansB = b[j]
ansC = c[k]
return [ansA, ansB, ansC]
#Driver Code Starts
if __name__ == '__main__':
a = [1, 4, 10]
b = [2, 15, 20]
c = [10, 12]
ans = findCloset(a, b, c)
print(*ans)
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GFG {
//Driver Code Ends
static List<int> findCloset(int[] a, int[] b, int[] c) {
int n1 = a.Length, n2 = b.Length, n3 = c.Length;
int minval = int.MaxValue;
int ansA = 0, ansB = 0, ansC = 0;
// try all triplets
for(int i = 0; i < n1; i++) {
for(int j = 0; j < n2; j++) {
for(int k = 0; k < n3; k++) {
int val = Math.Max(Math.Abs(a[i]-b[j]),
Math.Max(Math.Abs(b[j]-c[k]),
Math.Abs(c[k]-a[i])));
if(val < minval) {
minval = val;
ansA = a[i];
ansB = b[j];
ansC = c[k];
}
}
}
}
return new List<int>{ansA, ansB, ansC};
}
//Driver Code Starts
static void Main() {
int[] a = {1, 4, 10};
int[] b = {2, 15, 20};
int[] c = {10, 12};
List<int> ans = findCloset(a, b, c);
foreach(int x in ans) Console.Write(x + " ");
Console.WriteLine();
}
}
//Driver Code Ends
function findCloset(a, b, c) {
let n1 = a.length, n2 = b.length, n3 = c.length;
let minval = Infinity;
let ansA = 0, ansB = 0, ansC = 0;
// try all triplets
for(let i = 0; i < n1; i++) {
for(let j = 0; j < n2; j++) {
for(let k = 0; k < n3; k++) {
let val = Math.max(Math.abs(a[i]-b[j]),
Math.abs(b[j]-c[k]), Math.abs(c[k]-a[i]));
if(val < minval) {
minval = val;
ansA = a[i];
ansB = b[j];
ansC = c[k];
}
}
}
}
return [ansA, ansB, ansC];
}
//Driver Code Starts
// Driver code
let a = [1, 4, 10];
let b = [2, 15, 20];
let c = [10, 12];
let ans = findCloset(a, b, c);
console.log(ans.join(" "));
//Driver Code Ends
Output
10 15 10
[Expected Approach] Using Single Traversal - O(n1+n2+n3) time and O(1) Space
The problem can be reformulated as finding the triplet (a[i], b[j], c[k]) that minimizes the difference between the maximum and minimum elements among the three. Since the arrays are sorted, we can use a three pointer approach.
We start with pointers at the beginning of each array. At every step, the elements pointed to form a candidate triplet. To minimize max - min, we need to reduce the gap between the largest and smallest values in this triplet. The most effective way to achieve this is to advance the pointer pointing to the smallest element among the three, because increasing the minimum value can potentially reduce the difference in the next step.
We continue this process as long as all three pointers remain within their arrays. During the traversal, we keep track of the smallest max - min encountered and the corresponding triplet. At the end, the triplet with the minimum difference is returned as the answer.
//Driver Code Starts
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
//Driver Code Ends
vector<int> findCloset(vector<int>& a, vector<int>& b,
vector<int>& c) {
int i = 0, j = 0, k = 0;
int n1 = a.size(), n2 = b.size(), n3 = c.size();
int minDiff = INT_MAX;
int ansA = 0, ansB = 0, ansC = 0;
// Use three pointers to traverse the arrays
while(i < n1 && j < n2 && k < n3) {
int currentMax = max({a[i], b[j], c[k]});
int currentMin = min({a[i], b[j], c[k]});
int diff = currentMax - currentMin;
// Update answer if current difference is smaller
if(diff < minDiff) {
minDiff = diff;
ansA = a[i];
ansB = b[j];
ansC = c[k];
}
// Move the pointer pointing to the smallest element
if(a[i] == currentMin) i++;
else if(b[j] == currentMin) j++;
else k++;
}
return {ansA, ansB, ansC};
}
//Driver Code Starts
int main() {
vector<int> a = {1, 4, 10};
vector<int> b = {2, 15, 20};
vector<int> c = {10, 12};
vector<int> ans = findCloset(a, b, c);
for(int x : ans) cout << x << " ";
cout << endl;
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
import java.util.Arrays;
class GFG {
//Driver Code Ends
static ArrayList<Integer> findCloset(int[] a, int[] b, int[] c) {
int i = 0, j = 0, k = 0;
int n1 = a.length, n2 = b.length, n3 = c.length;
int minDiff = Integer.MAX_VALUE;
int ansA = 0, ansB = 0, ansC = 0;
// Use three pointers to traverse the arrays
while(i < n1 && j < n2 && k < n3) {
int currentMax = Math.max(a[i], Math.max(b[j], c[k]));
int currentMin = Math.min(a[i], Math.min(b[j], c[k]));
int diff = currentMax - currentMin;
// Update answer if current difference is smaller
if(diff < minDiff) {
minDiff = diff;
ansA = a[i];
ansB = b[j];
ansC = c[k];
}
// Move the pointer pointing to the smallest element
if(a[i] == currentMin) i++;
else if(b[j] == currentMin) j++;
else k++;
}
return new ArrayList<>(Arrays.asList(ansA, ansB, ansC));
}
//Driver Code Starts
public static void main(String[] args) {
int[] a = {1, 4, 10};
int[] b = {2, 15, 20};
int[] c = {10, 12};
ArrayList<Integer> ans = findCloset(a, b, c);
for(int x : ans) System.out.print(x + " ");
System.out.println();
}
}
//Driver Code Ends
def findCloset(a, b, c):
i = j = k = 0
n1, n2, n3 = len(a), len(b), len(c)
minDiff = float('inf')
ansA = ansB = ansC = 0
# Use three pointers to traverse the arrays
while i < n1 and j < n2 and k < n3:
currentMax = max(a[i], b[j], c[k])
currentMin = min(a[i], b[j], c[k])
diff = currentMax - currentMin
# Update answer if current difference is smaller
if diff < minDiff:
minDiff = diff
ansA, ansB, ansC = a[i], b[j], c[k]
# Move the pointer pointing to the smallest element
if a[i] == currentMin:
i += 1
elif b[j] == currentMin:
j += 1
else:
k += 1
return [ansA, ansB, ansC]
#Driver Code Starts
if __name__ == '__main__':
a = [1, 4, 10]
b = [2, 15, 20]
c = [10, 12]
ans = findCloset(a, b, c)
print(*ans)
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GFG {
//Driver Code Ends
static List<int> findCloset(int[] a, int[] b, int[] c) {
int i = 0, j = 0, k = 0;
int n1 = a.Length, n2 = b.Length, n3 = c.Length;
int minDiff = int.MaxValue;
int ansA = 0, ansB = 0, ansC = 0;
// Use three pointers to traverse the arrays
while(i < n1 && j < n2 && k < n3) {
int currentMax = Math.Max(a[i], Math.Max(b[j], c[k]));
int currentMin = Math.Min(a[i], Math.Min(b[j], c[k]));
int diff = currentMax - currentMin;
// Update answer if current difference is smaller
if(diff < minDiff) {
minDiff = diff;
ansA = a[i];
ansB = b[j];
ansC = c[k];
}
// Move the pointer pointing to the smallest element
if(a[i] == currentMin) i++;
else if(b[j] == currentMin) j++;
else k++;
}
return new List<int>{ansA, ansB, ansC};
}
//Driver Code Starts
static void Main() {
int[] a = {1, 4, 10};
int[] b = {2, 15, 20};
int[] c = {10, 12};
List<int> ans = findCloset(a, b, c);
foreach(int x in ans) Console.Write(x + " ");
Console.WriteLine();
}
}
//Driver Code Ends
function findCloset(a, b, c) {
let i = 0, j = 0, k = 0;
let n1 = a.length, n2 = b.length, n3 = c.length;
let minDiff = Infinity;
let ansA = 0, ansB = 0, ansC = 0;
// Use three pointers to traverse the arrays
while(i < n1 && j < n2 && k < n3) {
let currentMax = Math.max(a[i], b[j], c[k]);
let currentMin = Math.min(a[i], b[j], c[k]);
let diff = currentMax - currentMin;
// Update answer if current difference is smaller
if(diff < minDiff) {
minDiff = diff;
ansA = a[i];
ansB = b[j];
ansC = c[k];
}
// Move the pointer pointing to the smallest element
if(a[i] === currentMin) i++;
else if(b[j] === currentMin) j++;
else k++;
}
return [ansA, ansB, ansC];
}
//Driver Code Starts
// Driver code
let a = [1, 4, 10];
let b = [2, 15, 20];
let c = [10, 12];
let ans = findCloset(a, b, c);
console.log(ans.join(" "));
//Driver Code Ends
Output
10 15 10