Given n points on a Cartesian plane, find the number of pairs of points (A, B), where A and B do not coincide, such that the Manhattan distance and the Euclidean distance between them are equal.
Note:
- Manhattan Distance = |x2 - x1| + |y2 - y1|
- Euclidean Distance = sqrt((x2 - x1)^2 + (y2 - y1)^2), where the points are (x1, y1) and (x2, y2).
Examples:
Input: x[] = [1, 7], y[] = [1, 5]
Output: 0
Explanation: None of the pairs of points have equal Manhattan and Euclidean distance.Input: x[] = [1, 2, 1], y[]= [2, 3, 3]
Output: 2
Explanation: The pairs {(1,2), (1,3)} and {(1,3), (2,3)} have equal Manhattan and Euclidean distance.
Table of Content
[Naive Approach] Checking All Pairs - O(n ^ 2) Time and O(1) Space
The most direct idea is to check every pair of points one at a time: skip pairs that coincide, and for the rest, compute both the Manhattan and Euclidean distance directly and compare them. Since both sides are non-negative, comparing their squares avoids dealing with the square root at all.
Illustration:
- For x = [1,2,1], y = [2,3,3]: check pair (1,2) and (1,3) : dx=0, dy=1 : Manhattan =1, Euclidean2=1 : equal, count it
- Check (1,2) and (2,3) : dx = 1, dy = 1 : Manhattan =2, Manhattan2=4, Euclidean2=2 : not equal, skip
- Check (1,3) and (2,3) : dx = 1, dy = 0 : Manhattan =1, Euclidean2=1 : equal, count it
- Total of 2 valid pairs, matching the expected answer
#include <bits/stdc++.h>
using namespace std;
int numOfPairs(vector<int>& x, vector<int>& y) {
int n = x.size();
int ans = 0;
// Check every pair of points
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// Skip pairs of coinciding points
if (x[i] == x[j] && y[i] == y[j]) continue;
long long dx = abs(x[i] - x[j]);
long long dy = abs(y[i] - y[j]);
long long manhattan = dx + dy;
long long euclidSquared = dx * dx + dy * dy;
// Compare squared distances to avoid floating point square roots
if (manhattan * manhattan == euclidSquared) ans++;
}
}
return ans;
}
int main() {
vector<int> x = {1, 2, 1};
vector<int> y = {2, 3, 3};
cout << numOfPairs(x, y) << endl;
return 0;
}
class GfG {
static int numOfPairs(int[] x, int[] y) {
int n = x.length;
int ans = 0;
// Check every pair of points
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// Skip pairs of coinciding points
if (x[i] == x[j] && y[i] == y[j]) continue;
long dx = Math.abs(x[i] - x[j]);
long dy = Math.abs(y[i] - y[j]);
long manhattan = dx + dy;
long euclidSquared = dx * dx + dy * dy;
// Compare squared distances to avoid floating point square roots
if (manhattan * manhattan == euclidSquared) ans++;
}
}
return ans;
}
public static void main(String[] args) {
int[] x = {1, 2, 1};
int[] y = {2, 3, 3};
System.out.println(numOfPairs(x, y));
}
}
def numOfPairs(x, y):
n = len(x)
ans = 0
# Check every pair of points
for i in range(n):
for j in range(i + 1, n):
# Skip pairs of coinciding points
if x[i] == x[j] and y[i] == y[j]:
continue
dx = abs(x[i] - x[j])
dy = abs(y[i] - y[j])
manhattan = dx + dy
euclid_squared = dx * dx + dy * dy
# Compare squared distances to avoid floating point square roots
if manhattan * manhattan == euclid_squared:
ans += 1
return ans
if __name__ == "__main__":
x = [1, 2, 1]
y = [2, 3, 3]
print(numOfPairs(x, y))
using System;
class GfG {
static int numOfPairs(int[] x, int[] y) {
int n = x.Length;
int ans = 0;
// Check every pair of points
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// Skip pairs of coinciding points
if (x[i] == x[j] && y[i] == y[j]) continue;
long dx = Math.Abs(x[i] - x[j]);
long dy = Math.Abs(y[i] - y[j]);
long manhattan = dx + dy;
long euclidSquared = dx * dx + dy * dy;
// Compare squared distances to avoid floating point square roots
if (manhattan * manhattan == euclidSquared) ans++;
}
}
return ans;
}
static void Main() {
int[] x = { 1, 2, 1 };
int[] y = { 2, 3, 3 };
Console.WriteLine(numOfPairs(x, y));
}
}
function numOfPairs(x, y) {
let n = x.length;
let ans = 0;
// Check every pair of points
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
// Skip pairs of coinciding points
if (x[i] === x[j] && y[i] === y[j]) continue;
let dx = Math.abs(x[i] - x[j]);
let dy = Math.abs(y[i] - y[j]);
let manhattan = dx + dy;
let euclidSquared = dx * dx + dy * dy;
// Compare squared distances to avoid floating point square roots
if (manhattan * manhattan === euclidSquared) ans++;
}
}
return ans;
}
// driver code
let x = [1, 2, 1];
let y = [2, 3, 3];
console.log(numOfPairs(x, y));
Output
2
[Expected Approach] Grouping by Coordinate - O(n) Time and O(n) Space
Group points by their x value and separately by their y value. Within any group of m points sharing a coordinate, every pair among them is automatically valid, contributing C(m,2) pairs. Summing this across all x-groups and all y-groups counts every valid pair - except points that are exact duplicates get counted once in their x-group and once in their y-group, even though they should contribute zero (since coinciding points are excluded), so their contribution must be subtracted out twice.
Illustration:
- For x=[1,2,1], y=[2,3,3]: group by x : x=1 has points at indices 0,2 (2 points) : contributes C(2,2)=1
- Group by y : y=3 has points at indices 1,2 (2 points) : contributes C(2,2)=1
- No exact duplicate points exist here, so nothing needs to be subtracted
- Total: 1 + 1 = 2, matching the expected answer
#include <bits/stdc++.h>
using namespace std;
int numOfPairs(vector<int>& x, vector<int>& y) {
int n = x.size();
unordered_map<int, int> xCount, yCount;
map<pair<int, int>, int> pointCount;
// Count occurrences of each x value, each y value, and each exact point
for (int i = 0; i < n; i++) {
xCount[x[i]]++;
yCount[y[i]]++;
pointCount[{x[i], y[i]}]++;
}
long long ans = 0;
// Add pairs sharing the same x, and pairs sharing the same y
for (auto& p : xCount) ans += (long long)p.second * (p.second - 1) / 2;
for (auto& p : yCount) ans += (long long)p.second * (p.second - 1) / 2;
// Subtract twice the pairs of exactly coinciding points, since they were
// wrongly counted once in the x-group sum and once in the y-group sum
for (auto& p : pointCount) ans -= 2 * ((long long)p.second * (p.second - 1) / 2);
return (int)ans;
}
int main() {
vector<int> x = {1, 2, 1};
vector<int> y = {2, 3, 3};
cout << numOfPairs(x, y) << endl;
return 0;
}
import java.util.*;
class GfG {
static int numOfPairs(int[] x, int[] y) {
int n = x.length;
Map<Integer, Integer> xCount = new HashMap<>();
Map<Integer, Integer> yCount = new HashMap<>();
Map<String, Integer> pointCount = new HashMap<>();
// Count occurrences of each x value, each y value, and each exact point
for (int i = 0; i < n; i++) {
xCount.put(x[i], xCount.getOrDefault(x[i], 0) + 1);
yCount.put(y[i], yCount.getOrDefault(y[i], 0) + 1);
String key = x[i] + "," + y[i];
pointCount.put(key, pointCount.getOrDefault(key, 0) + 1);
}
long ans = 0;
// Add pairs sharing the same x, and pairs sharing the same y
for (int v : xCount.values()) ans += (long) v * (v - 1) / 2;
for (int v : yCount.values()) ans += (long) v * (v - 1) / 2;
// Subtract twice the pairs of exactly coinciding points, since they were
// wrongly counted once in the x-group sum and once in the y-group sum
for (int v : pointCount.values()) ans -= 2 * ((long) v * (v - 1) / 2);
return (int) ans;
}
public static void main(String[] args) {
int[] x = {1, 2, 1};
int[] y = {2, 3, 3};
System.out.println(numOfPairs(x, y));
}
}
def numOfPairs(x, y):
n = len(x)
xCount = {}
yCount = {}
pointCount = {}
# Count occurrences of each x value, each y value, and each exact point
for i in range(n):
xCount[x[i]] = xCount.get(x[i], 0) + 1
yCount[y[i]] = yCount.get(y[i], 0) + 1
key = (x[i], y[i])
pointCount[key] = pointCount.get(key, 0) + 1
ans = 0
# Add pairs sharing the same x, and pairs sharing the same y
for v in xCount.values():
ans += v * (v - 1) // 2
for v in yCount.values():
ans += v * (v - 1) // 2
# Subtract twice the pairs of exactly coinciding points, since they were
# wrongly counted once in the x-group sum and once in the y-group sum
for v in pointCount.values():
ans -= 2 * (v * (v - 1) // 2)
return ans
if __name__ == "__main__":
x = [1, 2, 1]
y = [2, 3, 3]
print(numOfPairs(x, y))
using System;
using System.Collections.Generic;
class GfG {
static int numOfPairs(int[] x, int[] y) {
int n = x.Length;
Dictionary<int, int> xCount = new Dictionary<int, int>();
Dictionary<int, int> yCount = new Dictionary<int, int>();
Dictionary<(int, int), int> pointCount = new Dictionary<(int, int), int>();
// Count occurrences of each x value, each y value, and each exact point
for (int i = 0; i < n; i++) {
if (xCount.ContainsKey(x[i])) xCount[x[i]]++; else xCount[x[i]] = 1;
if (yCount.ContainsKey(y[i])) yCount[y[i]]++; else yCount[y[i]] = 1;
var key = (x[i], y[i]);
if (pointCount.ContainsKey(key)) pointCount[key]++; else pointCount[key] = 1;
}
long ans = 0;
// Add pairs sharing the same x, and pairs sharing the same y
foreach (int v in xCount.Values) ans += (long)v * (v - 1) / 2;
foreach (int v in yCount.Values) ans += (long)v * (v - 1) / 2;
// Subtract twice the pairs of exactly coinciding points, since they were
// wrongly counted once in the x-group sum and once in the y-group sum
foreach (int v in pointCount.Values) ans -= 2 * ((long)v * (v - 1) / 2);
return (int)ans;
}
static void Main() {
int[] x = { 1, 2, 1 };
int[] y = { 2, 3, 3 };
Console.WriteLine(numOfPairs(x, y));
}
}
function numOfPairs(x, y) {
let n = x.length;
let xCount = new Map();
let yCount = new Map();
let pointCount = new Map();
// Count occurrences of each x value, each y value, and each exact point
for (let i = 0; i < n; i++) {
xCount.set(x[i], (xCount.get(x[i]) || 0) + 1);
yCount.set(y[i], (yCount.get(y[i]) || 0) + 1);
let key = x[i] + "," + y[i];
pointCount.set(key, (pointCount.get(key) || 0) + 1);
}
let ans = 0;
// Add pairs sharing the same x, and pairs sharing the same y
for (let v of xCount.values()) ans += v * (v - 1) / 2;
for (let v of yCount.values()) ans += v * (v - 1) / 2;
// Subtract twice the pairs of exactly coinciding points, since they were
// wrongly counted once in the x-group sum and once in the y-group sum
for (let v of pointCount.values()) ans -= 2 * (v * (v - 1) / 2);
return ans;
}
// driver code
let x = [1, 2, 1];
let y = [2, 3, 3];
console.log(numOfPairs(x, y));
Output
2