The problem is, given a list of coordinates, determine the number of k coordinates that are closest to the origin.
I have been able to determine the distance between the points and origin, however when filtering for the closest k points, I am lost. I decided to place this logic in a the second for loop, sort the array of distance from closest to furthest, and push the values that are less than K.
function kClosest(points, k) {
let length = [];
let arr = [];
let result = [];
let a = 0;
let b = 0;
for (let i = 0; i < points.length; i++) {
a = points[i][0]; //x coord
b = points[i][1]; //y coord (y will always be second number or '1')
length.push(parseFloat(calcHypotenuse(a, b).toFixed(4)))
arr.push([points[i], length[i]])
}
function calcHypotenuse(a, b) {
return (Math.sqrt((a * a) + (b * b)));
}
for (let i = 0; i < k; i++) {
arr = arr.sort();
result.push(arr[i][0])
}
return result;
}
console.log(kClosest([
[-5, 4],
[-6, -5],
[4, 6]
], K = 2))
The problem is, given a list of coordinates, determine the number of k coordinates that are closest to the origin.
I have been able to determine the distance between the points and origin, however when filtering for the closest k points, I am lost. I decided to place this logic in a the second for loop, sort the array of distance from closest to furthest, and push the values that are less than K.
function kClosest(points, k) {
let length = [];
let arr = [];
let result = [];
let a = 0;
let b = 0;
for (let i = 0; i < points.length; i++) {
a = points[i][0]; //x coord
b = points[i][1]; //y coord (y will always be second number or '1')
length.push(parseFloat(calcHypotenuse(a, b).toFixed(4)))
arr.push([points[i], length[i]])
}
function calcHypotenuse(a, b) {
return (Math.sqrt((a * a) + (b * b)));
}
for (let i = 0; i < k; i++) {
arr = arr.sort();
result.push(arr[i][0])
}
return result;
}
console.log(kClosest([
[-5, 4],
[-6, -5],
[4, 6]
], K = 2))
Expected output: [-5, 4], [4, 6] // I had [-5, 4], [-6, -5]
Share Improve this question asked Feb 5, 2019 at 23:16 Tyler MoralesTyler Morales 1,8586 gold badges30 silver badges69 bronze badges 1- Possible duplicate of Finding the first n largest elements in an array – Redu Commented Feb 10, 2019 at 19:32
2 Answers
Reset to default 5Sorting the whole array is wasteful, and may not even be possible. It is wasteful because the question didn't ask for a total ordering of all the elements, not even the k
elements. Sorting using a parison-based sort takes O(n log(n))
time. More generally, if the input is a stream of numbers, storing all of them in the memory and sorting them may not even be possible.
I don't know much about JavaScript, but on general algorithmic turf, we can solve this problem faster using one of the following 2 methods:
- Using a Max Priority Queue: Create a max PQ with an ordering based on the distance from the origin. Keep inserting the elements in the max PQ, and whenever the size exceeds
k
, remove the top element (the maximum). In the end, the PQ would have thek
smallest elements. Space plexity:O(k)
, time plexity:O(n log(k))
which fork << n
, may be close toO(n)
. - Using Quick-select: Run quick-select k times on the input. This assumes the input fits in the memory (space
O(n)
), but runs inO(nk)
time, which fork << n
, may be close toO(n)
.
I suggest using a custom sort for this - you can pass Array.sort()
a parison function, like this:
function kClosest(points, k) {
//sorts the array in place
points.sort((point1, point2) => {
const distanceFromOrigin1 = getDistanceFromOrigin(point1);
const distanceFromOrigin2 = getDistanceFromOrigin(point2);
//sort by distance from origin, lowest first
return distanceFromOrigin1 - distanceFromOrigin2;
});
//returns first k elements
return points.slice(0, k);
}
function getDistanceFromOrigin(point) {
const [x, y] = point; //array destructuring
return (x*x) + (y*y);
}
console.log(kClosest([
[-5, 4],
[-6, -5],
[4, 6]
], 2))
See https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort for more details on custom sorting.