给定一个由N 个整数组成的排序数组arr[] ,代表一条线上的点和一个整数K ,任务是找到第一个点和最后一个点之间的任何点P ,使得所有给定点到P的距离之和相等到K。如果不存在这样的点,则打印“-1” 。
例子:
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
方法:给定的问题可以基于这样的观察来解决:距离的总和在阵列的中位数处将是最小的,并且当从中位数向任何末端移动时距离会增加。因此,我们的想法是对数组的两半执行二分搜索并检查是否有任何点的距离等于K 。请按照以下步骤解决问题:
- 声明一个函数,计算所有点到给定点的距离总和。
- 对数组的右半部分执行二分搜索,如下所示:
- 如果N 的值为奇数,则将left的值更新为arr[N / 2] 。否则,将left的值更新为arr[N / 2 – 1] + 1 。
- 如果N 的值为偶数,则将right的值更新为arr[N – 1] 。
- 找到距离的总和,比如temp from mid = (left + right) / 2并检查temp的值是否等于K 。如果发现为true ,则打印mid的值作为结果。
- 如果K < temp的值,则将right的值更新为mid – 1 。否则,将left的值更新为mid + 1 。
- 在数组的左半部分执行二分搜索:
- 设置left = arr[0]和right = arr[N / 2] – 1 的值。
- 查找距离的总和说,从2月中旬温度=(左+右)/并检查是否温度等于K或不是。如果发现为true ,则打印mid的值作为结果。
- 如果K > temp的值,则更新right = mid – 1的值。否则,更新left = mid + 1的值。
- 如果在左半部分和右半部分没有找到值,则打印“-1”作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the sum of distances
// of all points from a given point
int findSum(int* arr, int N, int pt)
{
// Stores sum of distances
int sum = 0;
// Traverse the array
for (int i = 0; i < N; i++) {
sum += abs(arr[i] - pt);
}
// Return the sum
return sum;
}
// Function to find such a point having
// sum of distances of all other points
// from this point equal to K
void findPoint(int* arr, int N, int K)
{
// If N is odd keep left as arr[n / 2]
// else keep left as arr[n / 2 - 1] + 1;
int left;
if (N % 2) {
left = arr[N / 2];
}
else {
left = arr[N / 2 - 1] + 1;
}
// Keep right as arr[N - 1]
int right = arr[N - 1];
// Perform binary search in the
// right half
while (left <= right) {
// Calculate the mid index
// of the range
int mid = (left + right) / 2;
int temp = findSum(arr, N, mid);
// If temp is equal to K
if (temp == K) {
// Print the value of mid
cout << mid << endl;
return;
}
// If the value of K < temp
else if (K < temp) {
// Update right to mid - 1
right = mid - 1;
}
// If the value of K > temp
else {
// Update left to mid + 1
left = mid + 1;
}
}
// Update the value of left
left = arr[0];
// Update the value of right
right = arr[N / 2] - 1;
// Perform binary search on the
// left half
while (left <= right) {
// Calculate the mid index
// of the range
int mid = (left + right) / 2;
int temp = findSum(arr, N, mid);
// If temp is equal to K
if (temp == K) {
// Print mid
cout << mid << endl;
return;
}
// if K > temp
else if (K > temp) {
// Update right to mid - 1
right = mid - 1;
}
// If K < temp
else {
// Update left to mid + 1
left = mid + 1;
}
}
// If no such point found
cout << "-1" << endl;
}
// Driver Code
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
// Java program for the above approach
import java.lang.*;
class GFG{
// Function to find the sum of distances
// of all points from a given point
public static int findSum(int arr[], int N,
int pt)
{
// Stores sum of distances
int sum = 0;
// Traverse the array
for(int i = 0; i < N; i++)
{
sum += Math.abs(arr[i] - pt);
}
// Return the sum
return sum;
}
// Function to find such a point having
// sum of distances of all other points
// from this point equal to K
public static void findPoint(int arr[], int N, int K)
{
// If N is odd keep left as arr[n / 2]
// else keep left as arr[n / 2 - 1] + 1;
int left;
if (N % 2 != 0)
{
left = arr[N / 2];
}
else
{
left = arr[N / 2 - 1] + 1;
}
// Keep right as arr[N - 1]
int right = arr[N - 1];
// Perform binary search in the
// right half
while (left <= right)
{
// Calculate the mid index
// of the range
int mid = (left + right) / 2;
int temp = findSum(arr, N, mid);
// If temp is equal to K
if (temp == K)
{
// Print the value of mid
System.out.println(mid);
return;
}
// If the value of K < temp
else if (K < temp)
{
// Update right to mid - 1
right = mid - 1;
}
// If the value of K > temp
else
{
// Update left to mid + 1
left = mid + 1;
}
}
// Update the value of left
left = arr[0];
// Update the value of right
right = arr[N / 2] - 1;
// Perform binary search on the
// left half
while (left <= right)
{
// Calculate the mid index
// of the range
int mid = (left + right) / 2;
int temp = findSum(arr, N, mid);
// If temp is equal to K
if (temp == K)
{
// Print mid
System.out.println(mid);
return;
}
// if K > temp
else if (K > temp)
{
// Update right to mid - 1
right = mid - 1;
}
// If K < temp
else
{
// Update left to mid + 1
left = mid + 1;
}
}
// If no such point found
System.out.println( "-1" );
}
// Driver Code
public static void main(String args[])
{
int arr[] = { 1, 3, 6, 7, 11 };
int K = 18;
int N = arr.length;
findPoint(arr, N, K);
}
}
// This code is contributed by SoumikMondal
Python3
# python 3 program for the above approach
# Function to find the sum of distances
# of all points from a given point
def findSum(arr, N, pt):
# Stores sum of distances
sum = 0
# Traverse the array
for i in range(N):
sum += abs(arr[i] - pt)
# Return the sum
return sum
# Function to find such a point having
# sum of distances of all other points
# from this point equal to K
def findPoint(arr, N, K):
# If N is odd keep left as arr[n / 2]
# else keep left as arr[n / 2 - 1] + 1;
left = 0
if (N % 2):
left = arr[N // 2]
else:
left = arr[N // 2 - 1] + 1
# Keep right as arr[N - 1]
right = arr[N - 1]
# Perform binary search in the
# right half
while (left <= right):
# Calculate the mid index
# of the range
mid = (left + right) // 2
temp = findSum(arr, N, mid)
# If temp is equal to K
if (temp == K):
# Print the value of mid
print(mid)
return
# If the value of K < temp
elif (K < temp):
# Update right to mid - 1
right = mid - 1
# If the value of K > temp
else:
# Update left to mid + 1
left = mid + 1
# Update the value of left
left = arr[0]
# Update the value of right
right = arr[N // 2] - 1
# Perform binary search on the
# left half
while (left <= right):
# Calculate the mid index
# of the range
mid = (left + right) // 2
temp = findSum(arr, N, mid)
# If temp is equal to K
if (temp == K):
# Print mid
print(mid)
return
# if K > temp
elif(K > temp):
# Update right to mid - 1
right = mid - 1
# If K < temp
else:
# Update left to mid + 1
left = mid + 1
# If no such point found
print("-1")
# Driver Code
if __name__ == '__main__':
arr = [1, 3, 6, 7, 11]
K = 18
N = len(arr)
findPoint(arr, N, K)
# This code is contributed by SURENDRA_GANGWAR.
8
时间复杂度: O(N * log 2 (M – m)) 其中M是最大值, m是数组的最小值。
辅助空间: O(1)