Created
February 20, 2021 19:58
-
-
Save joebutler2/5315f2e7e074171fd861e5a50d965a69 to your computer and use it in GitHub Desktop.
Point Distances with Shared Coordinate https://binarysearch.com/contest/Weekly-Contest-47-FeZJewLaN1?questionsetIndex=2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Solution { | |
solve(points) { | |
const byX = {}; | |
const byY = {}; | |
const result = []; | |
// points.sort((a,b) => a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]); | |
for(let [x, y] of points) { | |
byX[x] = byX[x] || []; | |
byX[x].push(y); | |
byY[y] = byY[y] || []; | |
byY[y].push(x); | |
} | |
for(let key in byX) { | |
byX[key].sort((a,b) => a - b); | |
} | |
for(let key in byY) { | |
byY[key].sort((a,b) => a - b); | |
} | |
this.byX = byX; | |
this.byY = byY; | |
console.log(byX, byY) | |
for(let i = 0; i < points.length; i++) { | |
let [x, y] = points[i]; | |
let dX = x; | |
let dY = y; | |
if(byX[x].length > 1 && byY[y].length == 1) { | |
// console.log("should be here") | |
// We don't want to match the same point. | |
dY = this.findClosestY(x, y)// (byX[x][0] == y) ? byX[x][1] : byX[x][0]; | |
} else if(byX[x].length == 1 && byY[y].length > 1) { | |
dX = this.findClosestX(x, y)// (byY[y][0] == x) ? byY[y][1] : byY[y][0]; | |
} else { // Then both points are valid. | |
let min = Number.MAX_SAFE_INTEGER; | |
// Try the point that matches on the X axis. | |
dY = this.findClosestY(x, y)//(byX[x][0] == y) ? byX[x][1] : byX[x][0]; | |
min = Math.min(manhattanDistance(x, dX, y, dY), min); | |
// Now try the point that matches on the Y axis. | |
dY = y; | |
dX = this.findClosestX(x, y);//(byY[y][0] == x) ? byY[y][1] : byY[y][0]; | |
min = Math.min(manhattanDistance(x, dX, y, dY), min); | |
result[i] = min; | |
continue; | |
} | |
// console.log(x,y, dX, dY) | |
result[i] = manhattanDistance(x, dX, y, dY); | |
} | |
return result; | |
} | |
findClosestX(x, y) { | |
let minValue = Number.MAX_SAFE_INTEGER; | |
let minDelta = Number.MAX_SAFE_INTEGER; | |
let index = binarySearch(this.byY[y], x); | |
for(let i = Math.max(index - 1, 0); i < Math.min(index + 1, this.byY[y].length); i++) { | |
if(i == index) continue; | |
let dX = this.byY[y][i]; | |
let delta = Math.abs(x - dX); | |
if(delta < minDelta) { | |
minValue = dX; | |
minDelta = delta; | |
} | |
} | |
return minValue; | |
} | |
findClosestY(x, y) { | |
let minValue = Number.MAX_SAFE_INTEGER; | |
let minDelta = Number.MAX_SAFE_INTEGER; | |
let index = binarySearch(this.byX[x], y); | |
for(let i = Math.max(index - 1, 0); i < Math.min(index + 1, this.byX[x].length); i++) { | |
if(i == index) continue; | |
let dY = this.byX[x][i]; | |
let delta = Math.abs(y - dY); | |
if(delta < minDelta) { | |
minValue = dY; | |
minDelta = delta; | |
} | |
} | |
return minValue; | |
} | |
} | |
const binarySearch = (target, arr) => { | |
return binarySearchRec(target, arr, 0, arr.length - 1); | |
} | |
const binarySearchRec = (target, arr, low, high) => { | |
if(low > high) return; | |
console.log("bs", target, low, high) | |
let mid = Math.floor(high - low / 2) + low; | |
if(arr[mid] == target) { | |
return mid; | |
} else if(arr[mid] < target) { | |
return binarySearchRec(target, arr, mid + 1, high); | |
} else { | |
return binarySearchRec(target, arr, low, mid - 1); | |
} | |
} | |
const manhattanDistance = (x, dX, y, dY) => | |
Math.abs(x - dX) + Math.abs(y - dY); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment