Given a sorted array arr[] and a value X, find the k closest elements to X in arr[].
Examples:
Input: K = 4, X = 35
arr[] = {12, 16, 22, 30, 35, 39, 42,
45, 48, 50, 53, 55, 56}
Output: 30 39 42 45
Note that if the element is present in array, then it should not be in output, only the other closest elements are required.
In the following solutions, it is assumed that all elements of array are distinct.
A simple solution is to do linear search for k closest elements.
1) Start from the first element and search for the crossover point (The point before which elements are smaller than or equal to X and after which elements are greater). This step takes O(n) time.
2) Once we find the crossover point, we can compare elements on both sides of crossover point to print k closest elements. This step takes O(k) time.
The time complexity of the above solution is O(n).
An Optimized Solution is to find k elements in O(Logn + k) time. The idea is to use Binary Search to find the crossover point. Once we find index of crossover point, we can print k closest elements in O(k) time.
[ad type=”banner”]
C++
c++
#include<stdio.h>
int findCrossOver(int arr[], int low, int high, int x)
{
if (arr[high] <= x)
return high;
if (arr[low] > x)
return low;
int mid = (low + high)/2;
if (arr[mid] <= x && arr[mid+1] > x)
return mid;
if(arr[mid] < x)
return findCrossOver(arr, mid+1, high, x);
return findCrossOver(arr, low, mid - 1, x);
}
void printKclosest(int arr[], int x, int k, int n)
{
int l = findCrossOver(arr, 0, n-1, x);
int r = l+1;
int count = 0;
if (arr[l] == x) l--;
while (l >= 0 && r < n && count < k)
{
if (x - arr[l] < arr[r] - x)
printf("%d ", arr[l--]);
else
printf("%d ", arr[r++]);
count++;
}
while (count < k && l >= 0)
printf("%d ", arr[l--]), count++;
while (count < k && r < n)
printf("%d ", arr[r++]), count++;
}
int main()
{
int arr[] ={12, 16, 22, 30, 35, 39, 42,
45, 48, 50, 53, 55, 56};
int n = sizeof(arr)/sizeof(arr[0]);
int x = 35, k = 4;
printKclosest(arr, x, 4, n);
return 0;
}
JAVA
java
class KClosest
{
int findCrossOver(int arr[], int low, int high, int x)
{
if (arr[high] <= x)
return high;
if (arr[low] > x)
return low;
int mid = (low + high)/2;
if (arr[mid] <= x && arr[mid+1] > x)
return mid;
if(arr[mid] < x)
return findCrossOver(arr, mid+1, high, x);
return findCrossOver(arr, low, mid - 1, x);
}
void printKclosest(int arr[], int x, int k, int n)
{
int l = findCrossOver(arr, 0, n-1, x);
int r = l+1;
int count = 0;
if (arr[l] == x) l--;
while (l >= 0 && r < n && count < k)
{
if (x - arr[l] < arr[r] - x)
System.out.print(arr[l--]+" ");
else
System.out.print(arr[r++]+" ");
count++;
}
while (count < k && l >= 0)
{
System.out.print(arr[l--]+" ");
count++;
}
while (count < k && r < n)
{
System.out.print(arr[r++]+" ");
count++;
}
}
public static void main(String args[])
{
KClosest ob = new KClosest();
int arr[] = {12, 16, 22, 30, 35, 39, 42,
45, 48, 50, 53, 55, 56
};
int n = arr.length;
int x = 35, k = 4;
ob.printKclosest(arr, x, 4, n);
}
}
Output:
39 30 42 45
The time complexity of this method is O(Logn + k).
[ad type=”banner”]