Find a point whose sum of distances from all given points on a line is K
Last Updated :
31 May, 2022
Given a sorted array arr[] consisting of N integers, representing points on a line and an integer K, the task is to find any point P between the first and last point such that the sum of distances of all given points from P is equal to K. If no such point exists, then print “-1”.
Examples:
Input: arr[] = {1, 3, 6, 7, 11}, K = 18
Output: 8
Explanation:
Consider the value of P as 8. Therefore, the sum of distance of P(= 8) from all points is (8 – 1) + (8 – 3) + (8 – 6) + (8 – 7) + (11 – 8) = 18( =K) which is equal to the given value K and the point 8 lies between the first(= 1) and the last(= 11) point.
Input: arr[] = {-10, -2, 1, 2}, K= 29
Output: -9
Approach: The given problem can be solved based on the observation that the sum of distances will be minimum at the median of the array and the distance increases when moved from the median towards any of the extremities. So, the idea is to perform a binary search on the both the halves of the array and check if any point has a distance equal to K. Follow the steps below to solve the problem:
- Declare a function that calculates the sum of distances of all points from a given point.
- Perform a binary search on the right half of the array as:
- If the value of N is odd, then update the value of left as arr[N / 2]. Otherwise, update the value of left as arr[N / 2 – 1] + 1.
- If the value of N is even, then update the value of right as arr[N – 1].
- Find the sum of distances say temp from mid = (left + right) / 2 and check if the value of temp is equal to K or not. IF found to be true, then print the value of mid as the result.
- If the value of K < temp, then update the value of right as mid – 1. Otherwise, update the value of left as mid + 1.
- Perform a binary search on the left half of the array:
- Set the value of left = arr[0] and right = arr[N / 2] – 1.
- Find the sum of distances say temp from mid = (left + right) / 2 and check if temp is equal to K or not. If found to be true, then print the value of mid as the result.
- If the value of K > temp, then update the value of right = mid – 1. Otherwise, update the value of left = mid + 1.
- If there is no value found in the left and right half then print “-1” as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int findSum( int * arr, int N, int pt)
{
int sum = 0;
for ( int i = 0; i < N; i++) {
sum += abs (arr[i] - pt);
}
return sum;
}
void findPoint( int * arr, int N, int K)
{
int left;
if (N % 2) {
left = arr[N / 2];
}
else {
left = arr[N / 2 - 1] + 1;
}
int right = arr[N - 1];
while (left <= right) {
int mid = (left + right) / 2;
int temp = findSum(arr, N, mid);
if (temp == K) {
cout << mid << endl;
return ;
}
else if (K < temp) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
left = arr[0];
right = arr[N / 2] - 1;
while (left <= right) {
int mid = (left + right) / 2;
int temp = findSum(arr, N, mid);
if (temp == K) {
cout << mid << endl;
return ;
}
else if (K > temp) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
cout << "-1" << endl;
}
int main()
{
int arr[] = { 1, 3, 6, 7, 11 };
int K = 18;
int N = sizeof (arr) / sizeof (arr[0]);
findPoint(arr, N, K);
return 0;
}
|
Java
import java.lang.*;
class GFG{
public static int findSum( int arr[], int N,
int pt)
{
int sum = 0 ;
for ( int i = 0 ; i < N; i++)
{
sum += Math.abs(arr[i] - pt);
}
return sum;
}
public static void findPoint( int arr[], int N, int K)
{
int left;
if (N % 2 != 0 )
{
left = arr[N / 2 ];
}
else
{
left = arr[N / 2 - 1 ] + 1 ;
}
int right = arr[N - 1 ];
while (left <= right)
{
int mid = (left + right) / 2 ;
int temp = findSum(arr, N, mid);
if (temp == K)
{
System.out.println(mid);
return ;
}
else if (K < temp)
{
right = mid - 1 ;
}
else
{
left = mid + 1 ;
}
}
left = arr[ 0 ];
right = arr[N / 2 ] - 1 ;
while (left <= right)
{
int mid = (left + right) / 2 ;
int temp = findSum(arr, N, mid);
if (temp == K)
{
System.out.println(mid);
return ;
}
else if (K > temp)
{
right = mid - 1 ;
}
else
{
left = mid + 1 ;
}
}
System.out.println( "-1" );
}
public static void main(String args[])
{
int arr[] = { 1 , 3 , 6 , 7 , 11 };
int K = 18 ;
int N = arr.length;
findPoint(arr, N, K);
}
}
|
Python3
def findSum(arr, N, pt):
sum = 0
for i in range (N):
sum + = abs (arr[i] - pt)
return sum
def findPoint(arr, N, K):
left = 0
if (N % 2 ):
left = arr[N / / 2 ]
else :
left = arr[N / / 2 - 1 ] + 1
right = arr[N - 1 ]
while (left < = right):
mid = (left + right) / / 2
temp = findSum(arr, N, mid)
if (temp = = K):
print (mid)
return
elif (K < temp):
right = mid - 1
else :
left = mid + 1
left = arr[ 0 ]
right = arr[N / / 2 ] - 1
while (left < = right):
mid = (left + right) / / 2
temp = findSum(arr, N, mid)
if (temp = = K):
print (mid)
return
elif (K > temp):
right = mid - 1
else :
left = mid + 1
print ( "-1" )
if __name__ = = '__main__' :
arr = [ 1 , 3 , 6 , 7 , 11 ]
K = 18
N = len (arr)
findPoint(arr, N, K)
|
C#
using System;
class GFG{
public static int findSum( int [] arr, int N, int pt)
{
int sum = 0;
for ( int i = 0; i < N; i++)
{
sum += Math.Abs(arr[i] - pt);
}
return sum;
}
public static void findPoint( int [] arr, int N, int K)
{
int left;
if (N % 2 != 0)
{
left = arr[N / 2];
}
else
{
left = arr[N / 2 - 1] + 1;
}
int right = arr[N - 1];
while (left <= right)
{
int mid = (left + right) / 2;
int temp = findSum(arr, N, mid);
if (temp == K)
{
Console.WriteLine(mid);
return ;
}
else if (K < temp)
{
right = mid - 1;
}
else
{
left = mid + 1;
}
}
left = arr[0];
right = arr[N / 2] - 1;
while (left <= right)
{
int mid = (left + right) / 2;
int temp = findSum(arr, N, mid);
if (temp == K)
{
Console.WriteLine(mid);
return ;
}
else if (K > temp)
{
right = mid - 1;
}
else
{
left = mid + 1;
}
}
Console.WriteLine( "-1" );
}
public static void Main( string [] args)
{
int [] arr = { 1, 3, 6, 7, 11 };
int K = 18;
int N = arr.Length;
findPoint(arr, N, K);
}
}
|
Javascript
<script>
function findSum(arr, N, pt)
{
var sum = 0;
var i;
for (i = 0; i < N; i++)
{
sum += Math.abs(arr[i] - pt);
}
return sum;
}
function findPoint(arr, N, K)
{
var left;
if (N % 2 == 1)
{
left = arr[parseInt(N / 2)];
}
else
{
left = arr[parseInt(N / 2) - 1] + 1;
}
var right = arr[N - 1];
while (left <= right)
{
var mid = parseInt((left + right) / 2);
var temp = findSum(arr, N, mid);
if (temp == K)
{
document.write(mid);
return ;
}
else if (K < temp)
{
right = mid - 1;
}
else
{
left = mid + 1;
}
}
left = arr[0];
right = arr[parseInt(N / 2)] - 1;
while (left <= right)
{
var mid = parseInt((left + right) / 2);
var temp = findSum(arr, N, mid);
if (temp == K)
{
document.write(mid);
return ;
}
else if (K > temp)
{
right = mid - 1;
}
else
{
left = mid + 1;
}
}
document.write( "-1" );
}
var arr = [ 1, 3, 6, 7, 11 ];
var K = 18;
var N = arr.length;
findPoint(arr, N, K);
</script>
|
Time Complexity: O(N * log2(M – m)) where M is maximum value and m is minimum value of the array.
Auxiliary Space: O(1)
Share your thoughts in the comments
Please Login to comment...