k-th smallest absolute difference of two elements in an array - GeeksforGeeks

05 Jan, 2022
We are given an array of size n containing positive integers. The absolute difference between values at indices i and j is |a[i] – a[j]|. There are n*(n-1)/2 such pairs and we are asked to print the kth (1 <= k <= n*(n-1)/2) the smallest absolute difference among all these pairs.Examples: 
Input  : a[] = {1, 2, 3, 4}
         k = 3
Output : 1
The possible absolute differences are :
{1, 2, 3, 1, 2, 1}.
The 3rd smallest value among these is 1.

Input : n = 2
        a[] = {10, 10}
        k = 1
Output : 0
Naive Method is to find all the n*(n-1)/2 possible absolute differences in O(n^2) and store them in an array. Then sort this array and print the k-th minimum value from this array. This will take time O(n^2 + n^2 * log(n^2)) = O(n^2 + 2*n^2*log(n)).The naive method won’t be efficient for large values of n, say n = 10^5.An Efficient Solution is based on Binary Search.  
1) Sort the given array a[].
2) We can easily find the least possible absolute
   difference in O(n) after sorting. The largest
   possible difference will be a[n-1] - a[0] after
   sorting the array. Let low = minimum_difference
   and high = maximum_difference.
3) while low < high:
4)     mid = (low + high)/2
5)     if ((number of pairs with absolute difference
                                <= mid) < k):
6)        low = mid + 1
7)     else:
8)        high = mid
9) return low
We need a function that will tell us the number of pairs with a difference <= mid efficiently. Since our array is sorted, this part can be done like this: 
1) result = 0
2) for i = 0 to n-1:
3)     result = result + (upper_bound(a+i, a+n, a[i] + mid) - (a+i+1))
4) return result
Here upper_bound is a variant of binary search which returns a pointer to the first element from a[i] to a[n-1] which is greater than a[i] + mid. Let the pointer returned be j. Then a[i] + mid < a[j]. Thus, subtracting (a+i+1) from this will give us the number of values whose difference with a[i] is <= mid. We sum this up for all indices from 0 to n-1 and get the answer for the current mid. 
C++
Java
Python3
C#
Javascript
// C++ program to find k-th absolute difference// between two elements#include<bits/stdc++.h>using namespace std;  // returns number of pairs with absolute difference// less than or equal to mid.int countPairs(int *a, int n, int mid){    int res = 0;    for (int i = 0; i < n; ++i)          // Upper bound returns pointer to position        // of next higher number than a[i]+mid in        // a[i..n-1]. We subtract (a + i + 1) from        // this position to count        res += upper_bound(a+i, a+n, a[i] + mid) -                                    (a + i + 1);    return res;}  // Returns k-th absolute differenceint kthDiff(int a[], int n, int k){    // Sort array    sort(a, a+n);      // Minimum absolute difference    int low = a[1] - a[0];    for (int i = 1; i <= n-2; ++i)        low = min(low, a[i+1] - a[i]);      // Maximum absolute difference    int high = a[n-1] - a[0];      // Do binary search for k-th absolute difference    while (low < high)    {        int mid = (low+high)>>1;        if (countPairs(a, n, mid) < k)            low = mid + 1;        else            high = mid;    }      return low;}  // Driver codeint main(){    int k = 3;    int a[] = {1, 2, 3, 4};    int n = sizeof(a)/sizeof(a[0]);    cout << kthDiff(a, n, k);    return 0;}
// Java program to find k-th absolute difference// between two elementsimport java.util.Scanner;import java.util.Arrays;  class GFG{    // returns number of pairs with absolute    // difference less than or equal to mid     static int countPairs(int[] a, int n, int mid)    {        int res = 0, value;        for(int i = 0; i < n; i++)        {            // Upper bound returns pointer to position            // of next higher number than a[i]+mid in            // a[i..n-1]. We subtract (ub + i + 1) from            // this position to count             if(a[i]+mid>a[n-1])              res+=(n-(i+1));            else            {             int ub = upperbound(a, n, a[i]+mid);             res += (ub- (i+1));            }        }        return res;    }      // returns the upper bound    static int upperbound(int a[], int n, int value)    {        int low = 0;        int high = n;        while(low < high)        {            final int mid = (low + high)/2;            if(value >= a[mid])                low = mid + 1;            else                high = mid;        }      return low;    }      // Returns k-th absolute difference    static int kthDiff(int a[], int n, int k)    {        // Sort array        Arrays.sort(a);          // Minimum absolute difference        int low = a[1] - a[0];        for (int i = 1; i <= n-2; ++i)            low = Math.min(low, a[i+1] - a[i]);          // Maximum absolute difference        int high = a[n-1] - a[0];          // Do binary search for k-th absolute difference        while (low < high)        {            int mid = (low + high) >> 1;            if (countPairs(a, n, mid) < k)                low = mid + 1;            else                high = mid;        }          return low;    }      // Driver function to check the above functions    public static void main(String args[])    {        Scanner s = new Scanner(System.in);        int k = 3;        int a[] = {1,2,3,4};        int n = a.length;        System.out.println(kthDiff(a, n, k));    }  }// This code is contributed by nishkarsh146
# Python3 program to find # k-th absolute difference # between two elements from bisect import bisect as upper_bound   # returns number of pairs with # absolute difference less than # or equal to mid. def countPairs(a, n, mid):     res = 0    for i in range(n):           # Upper bound returns pointer to position         # of next higher number than a[i]+mid in         # a[i..n-1]. We subtract (a + i + 1) from         # this position to count         res += upper_bound(a, a[i] + mid)     return res   # Returns k-th absolute difference def kthDiff(a, n, k):           # Sort array     a = sorted(a)       # Minimum absolute difference     low = a[1] - a[0]     for i in range(1, n - 1):         low = min(low, a[i + 1] - a[i])       # Maximum absolute difference     high = a[n - 1] - a[0]       # Do binary search for k-th absolute difference     while (low < high):         mid = (low + high) >> 1        if (countPairs(a, n, mid) < k):             low = mid + 1        else:             high = mid       return low   # Driver code k = 3a = [1, 2, 3, 4] n = len(a) print(kthDiff(a, n, k))   # This code is contributed by Mohit Kumar 
// C# program to find k-th // absolute difference// between two elementsusing System;class GFG{     // returns number of pairs // with absolute difference // less than or equal to mid static int countPairs(int[] a,                       int n,                       int mid){  int res = 0;  for(int i = 0; i < n; i++)  {    // Upper bound returns pointer     // to position of next higher     // number than a[i]+mid in    // a[i..n-1]. We subtract     // (ub + i + 1) from    // this position to count     int ub = upperbound(a, n,                        a[i] + mid);    res += (ub - (i));  }  return res;}  // returns the upper boundstatic int upperbound(int []a,                       int n,                       int value){  int low = 0;  int high = n;  while(low < high)  {    int mid = (low + high)/2;    if(value >= a[mid])      low = mid + 1;    else      high = mid;  }    return low;}  // Returns k-th absolute // differencestatic int kthDiff(int []a,                    int n, int k){  // Sort array  Array.Sort(a);    // Minimum absolute   // difference  int low = a[1] - a[0];  for (int i = 1; i <= n - 2; ++i)    low = Math.Min(low, a[i + 1] -                    a[i]);    // Maximum absolute   // difference  int high = a[n - 1] - a[0];    // Do binary search for   // k-th absolute difference  while (low < high)  {    int mid = (low + high) >> 1;    if (countPairs(a, n, mid) < k)      low = mid + 1;    else      high = mid;  }    return low;}  // Driver codepublic static void Main(String []args){  int k = 3;  int []a = {1, 2, 3, 4};  int n = a.Length;  Console.WriteLine(kthDiff(a, n, k));}}  // This code is contributed by gauravrajput1
<script>  // JavaScript program to find k-th// absolute difference// between two elements    // returns number of pairs// with absolute difference// less than or equal to midfunction countPairs(a, n, mid) {    let res = 0;    for (let i = 0; i < n; i++) {        // Upper bound returns pointer        // to position of next higher        // number than a[i]+mid in        // a[i..n-1]. We subtract        // (ub + i + 1) from        // this position to count        let ub = upperbound(a, n,            a[i] + mid);        res += (ub - (i));    }    return res;}  // returns the upper boundfunction upperbound(a, n, value) {    let low = 0;    let high = n;    while (low < high) {        let mid = (low + high) / 2;        if (value >= a[mid])            low = mid + 1;        else            high = mid;    }      return low;}  // Returns k-th absolute// differencefunction kthDiff(a, n, k) {    // Sort array    a.sort((a, b) => a - b);      // Minimum absolute    // difference    let low = a[1] - a[0];    for (let i = 1; i <= n - 2; ++i)        low = Math.min(low, a[i + 1] -            a[i]);      // Maximum absolute    // difference    let high = a[n - 1] - a[0];      // Do binary search for    // k-th absolute difference    while (low < high) {        let mid = (low + high) >> 1;        if (countPairs(a, n, mid) < k)            low = mid + 1;        else            high = mid;    }      return low;}  // Driver code  let k = 3;let a = [1, 2, 3, 4];let n = a.length;document.write(kthDiff(a, n, k));      // This code is contributed by gfgking  </script>
Output:  
1
Suppose, maximum element in the array is , and minimum element is minimum element in the array is .
Then time taken for the binary_search will be , and time taken for the upper_bound function will be . 
So, the time complexity of the algorithm is . Sorting takes . After that the main binary search over low and high takes  time because each call to the function countPairs takes time . 
So the Overall time complexity would be  
YouTubeGeeksforGeeks500K subscribersk-th smallest absolute difference of two elements in an array | GeeksforGeeksWatch laterShareCopy linkInfoShoppingTap to unmuteIf playback doesn't begin shortly, try restarting your device.You're signed outVideos you watch may be added to the TV's watch history and influence TV recommendations. To avoid this, cancel and sign in to YouTube on your computer.CancelConfirmMore videosMore videosSwitch cameraShareInclude playlistAn error occurred while retrieving sharing information. Please try again later.Watch on0:000:000:00 / 4:18•Live•<div class="player-unavailable"><h1 class="message">An error occurred.</h1><div class="submessage"><a href="https://www.youtube.com/watch?v=ZXpYPeRE66E" target="_blank">Try watching this video on www.youtube.com</a>, or enable JavaScript if it is disabled in your browser.</div></div>
?list=PLqM7alHXFySEQDk2MDfbwEdjd2svVJH9p 
This article is contributed by Hemang Sarkar. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
mohit kumar 29
nishkarsh146
GauravRajput1
gfgking
sankcan55
executionover
Binary Search
Order-Statistics
Arrays
Arrays
Binary Search
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Arrays in Java
Stack Data Structure (Introduction and Program)
Arrays in C/C++
Multidimensional Arrays in Java
Python | Using 2D arrays/lists the right way
Queue | Set 1 (Introduction and Array Implementation)
Largest Sum Contiguous Subarray
Linear Search
Program for array rotation
Program to find largest element in an array