Given N points in the 2D plane such that each point has a weight Wi. The task is to find a point K such that the sum of the total distance between point K and each point is minimized, such that
- The distance between point K and point Pi is calculated as Manhattan distance(K, Pi)*Wi. (i.e., Manhattan Distance between point K and Pi multiplied by the weight of point Pi).
- Manhattan distance is the distance between two points measured along axes at right angles. In a plane with p1 at (x1, y1) and p2 at (x2, y2), it is |x1 – x2| + |y1 – y2|.
Examples:
Input: N = 2, Points = [ [0, 0], [2, 2] ], Weights = [1, 2]
Output: 4
Explanation: Point K chosen here is (2,2). So total sum of Distance is 1*(2+2)+2*(0+0)=4Input: N = 2, Points = [ [0, 0], [2, 2] ], Weights = [1, 1]
Output: 4
Explanation: Point K chosen here is (1,1). So total sum of Distance is 1*(1+1)+1*(1+1)=4
Naive Approach:
If we solve this problem using the Naive Approach, we will be doing hit and trial to find a suitable point that satisfies the required conditions for K.
Efficient Approach:
Idea:
If we follow the Naive Approach, there can be a lot of possibilities and the code can give TLE for large constraints. So we need to find a way to minimize our pool of possible points for K.
To optimize this approach, consider the below observations:
- If we don’t consider the weights of each point, the required Point of minimum sum of distance will be around the center (of the polygon formed through given points).
- However since the input is a list of points in the 2D plane, we cannot find the center directly. Instead, we will be using the Geometric Median.
- Now to find the Minimum sum of distance for weighted points, we can modify this Median property to find the weighted center.
Step-by-Step Approach:
- Store the x-coordinate and y-coordinate of all the N points separately in an array.
- To find the x-coordinate of point K take the weighted median of all the x-coordinates of the N points.
- Similarly, to find the y-coordinate of point K take the weighted median of all the y-coordinates of the points.
- Now calculate the sum of the distance between point K and all the N points considering their weights.
Illustration:
- To find the x-coordinate and y-coordinate of point K we will take the weighted median of the x-coordinates and y-coordinates of all the points respectively.
- x-coordinate of point K will median of [1, 1, 4, 4, 4, 7, 7] which will be 4, and the y-coordinate of point K will median of [1, 1, 1, 4, 4, 7, 7] which will also be 4.
- Point K will be (4,4)
- The Sum of the Distance of point K from each point will be 21, which is the minimum sum of distance possible.
Below is the implementation of the above approach:
#include <bits/stdc++.h> using namespace std;
class GFG {
public :
// Finds the median of an array
int FindMedian(vector< int > cord)
{
int n = cord.size();
// If size is odd then median is the middle element.
if (n % 2 == 1) {
return cord[n / 2];
}
// If size is even then median is mean of middle
// elements.
else {
return (cord[n / 2] + cord[n / 2 - 1]) / 2;
}
}
// To calculate minimum sum of distance between point k
// and all other points
int MinimizeSumOfDistance( int n,
vector<vector< int > > points,
vector< int > weights)
{
// Stores all x-coordinates of points
vector< int > x_cord;
// Stores all y-coordinates of points
vector< int > y_cord;
// Iterating through all the points
for ( int i = 0; i < n; i++) {
// Each point is pushed into the array amount of time
// equal to its weight
for ( int j = 0; j < weights[i]; j++) {
x_cord.push_back(points[i][0]);
y_cord.push_back(points[i][01]);
}
}
// Sorting all the x-coordinates and y-coordinates
sort(x_cord.begin(), x_cord.end());
sort(y_cord.begin(), y_cord.end());
// x-coordinate of point K
int x = FindMedian(x_cord);
// y-coordinate of point K
int y = FindMedian(y_cord);
// Stores the minimum sum of distance between point
// K and all other points.
int ans = 0;
// To calculate minimum sum of distance iterate
// through all the points.
for ( int i = 0; i < n; i++) {
ans = ans
+ weights[i]
* ( abs (x - points[i][0])
+ abs (y - points[i][1]));
}
return ans;
}
}; // Driver code int main()
{ GFG obj;
// Number of points
int n = 3;
// Stores all the points
vector<vector< int > > points{ { 1, 4 },
{ 4, 1 },
{ 7, 4 } };
// Stores weights of each point
vector< int > weights{ 2, 3, 2 };
cout << obj.MinimizeSumOfDistance(n, points, weights);
return 0;
} |
// Java code for the above approach import java.util.*;
class GFG {
// Finds the median of an array
public int FindMedian(List<Integer> cord)
{
int n = cord.size();
// If size is odd then median is the middle element.
if (n % 2 == 1 ) {
return cord.get(n / 2 );
}
// If size is even then median is mean of middle
// elements.
else {
return (cord.get(n / 2 ) + cord.get(n / 2 - 1 ))
/ 2 ;
}
}
// To calculate minimum sum of distance between point k
// and all other points
public int
MinimizeSumOfDistance( int n,
List<List<Integer> > points,
List<Integer> weights)
{
// Stores all x-coordinates of points
List<Integer> x_cord = new ArrayList<>();
// Stores all y-coordinates of points
List<Integer> y_cord = new ArrayList<>();
// Iterating through all the points
for ( int i = 0 ; i < n; i++) {
// Each point is pushed into the array amount of
// time equal to its weight
for ( int j = 0 ; j < weights.get(i); j++) {
x_cord.add(points.get(i).get( 0 ));
y_cord.add(points.get(i).get( 1 ));
}
}
// Sorting all the x-coordinates and y-coordinates
Collections.sort(x_cord);
Collections.sort(y_cord);
// x-coordinate of point K
int x = FindMedian(x_cord);
// y-coordinate of point K
int y = FindMedian(y_cord);
// Stores the minimum sum of distance between point
// K and all other points.
int ans = 0 ;
// To calculate minimum sum of distance iterate
// through all the points.
for ( int i = 0 ; i < n; i++) {
ans = ans
+ weights.get(i)
* (Math.abs(x
- points.get(i).get( 0 ))
+ Math.abs(
y - points.get(i).get( 1 )));
}
return ans;
}
// Driver code
public static void main(String[] args)
{
GFG obj = new GFG();
// Number of points
int n = 3 ;
// Stores all the points
List<List<Integer> > points = Arrays.asList(
Arrays.asList( 1 , 4 ), Arrays.asList( 4 , 1 ),
Arrays.asList( 7 , 4 ));
// Stores weights of each point
List<Integer> weights = Arrays.asList( 2 , 3 , 2 );
System.out.println(
obj.MinimizeSumOfDistance(n, points, weights));
}
} // This code is contributed by ragul21 |
# Finds the median of an array def find_median(cord):
n = len (cord)
# If size is odd, median is the middle element
if n % 2 = = 1 :
return cord[n / / 2 ]
# If size is even, median is mean of middle elements
else :
return (cord[n / / 2 ] + cord[n / / 2 - 1 ]) / 2
# To calculate minimum sum of distance between point K and all other points def minimize_sum_of_distance(n, points, weights):
# Stores all x-coordinates of points
x_cord = []
# Stores all y-coordinates of points
y_cord = []
# Iterating through all the points
for i in range (n):
# Each point is pushed into the array amount of time equal to its weight
for j in range (weights[i]):
x_cord.append(points[i][ 0 ])
y_cord.append(points[i][ 1 ])
# Sorting all the x-coordinates and y-coordinates
x_cord.sort()
y_cord.sort()
# x-coordinate of point K
x = find_median(x_cord)
# y-coordinate of point K
y = find_median(y_cord)
# Stores the minimum sum of distance between point K and all other points
ans = 0
# To calculate minimum sum of distance iterate through all the points
for i in range (n):
ans + = weights[i] * ( abs (x - points[i][ 0 ]) + abs (y - points[i][ 1 ]))
return ans
# Driver code if __name__ = = "__main__" :
# Number of points
n = 3
# Stores all the points
points = [[ 1 , 4 ], [ 4 , 1 ], [ 7 , 4 ]]
# Stores weights of each point
weights = [ 2 , 3 , 2 ]
print (minimize_sum_of_distance(n, points, weights))
#This code is contributed by Rohit Singh |
using System;
using System.Collections.Generic;
using System.Linq;
class GFG
{ // Finds the median of an array
private int FindMedian(List< int > cord)
{
int n = cord.Count;
if (n % 2 == 1)
{
return cord[n / 2];
}
// If size is even, then the median is the mean of middle elements.
else
{
return (cord[n / 2] + cord[n / 2 - 1]) / 2;
}
}
// To calculate the minimum sum of distance between
// point k and all other points
public int MinimizeSumOfDistance( int n, List<List< int >> points, List< int > weights)
{
// Stores all x-coordinates of points
List< int > xCord = new List< int >();
// Stores all y-coordinates of points
List< int > yCord = new List< int >();
// Iterating through all the points
for ( int i = 0; i < n; i++)
{
// Each point is pushed into the array
// the number of times equal to its weight
for ( int j = 0; j < weights[i]; j++)
{
xCord.Add(points[i][0]);
yCord.Add(points[i][1]);
}
}
// Sorting all the x-coordinates and y-coordinates
xCord.Sort();
yCord.Sort();
// x-coordinate of point K
int x = FindMedian(xCord);
// y-coordinate of point K
int y = FindMedian(yCord);
// Stores the minimum sum of distance between
// point K and all other points
int ans = 0;
// To calculate the minimum sum of distance
// iterate through all the points
for ( int i = 0; i < n; i++)
{
ans += weights[i] * (Math.Abs(x - points[i][0]) + Math.Abs(y - points[i][1]));
}
return ans;
}
} class Geek
{ static void Main()
{
GFG obj = new GFG();
// Number of points
int n = 3;
// Stores all the points
List<List< int >> points = new List<List< int >>
{
new List< int > { 1, 4 },
new List< int > { 4, 1 },
new List< int > { 7, 4 }
};
// Stores weights of each point
List< int > weights = new List< int > { 2, 3, 2 };
Console.WriteLine(obj.MinimizeSumOfDistance(n, points, weights));
}
} |
class GFG { Geek(cord) {
const n = cord.length;
// If size is odd, then median is the
// middle element.
if (n % 2 === 1) {
return cord[Math.floor(n / 2)];
}
else {
return Math.floor((cord[n / 2] + cord[n / 2 - 1]) / 2);
}
}
// To calculate minimum sum of distance between
// point k and all other points
minimizeSumOfDistance(n, points, weights) {
// Stores all x-coordinates of points
const x_cord = [];
const y_cord = [];
// Iterating through all the points
for (let i = 0; i < n; i++) {
for (let j = 0; j < weights[i]; j++) {
x_cord.push(points[i][0]);
y_cord.push(points[i][1]);
}
}
// Sorting all the x-coordinates and
// y-coordinates
x_cord.sort((a, b) => a - b);
y_cord.sort((a, b) => a - b);
// x-coordinate of point K
const x = this .Geek(x_cord);
const y = this .Geek(y_cord);
// Stores the minimum sum of distance between point K and
// all other points.
let ans = 0;
for (let i = 0; i < n; i++) {
ans += weights[i] * (Math.abs(x - points[i][0]) + Math.abs(y - points[i][1]));
}
return ans;
}
} // Driver code const obj = new GFG();
const n = 3; // Stores all the points const points = [ [1, 4],
[4, 1],
[7, 4]
]; // Stores weights of each point const weights = [2, 3, 2]; console.log(obj.minimizeSumOfDistance(n, points, weights)); |
21
Time Complexity: O(M*logM), where M is the sum of all the weights of N points.
Auxiliary Space: O(M)