This should be O(N):
def k_closest_points(points: List[List[int]], k: int) → List[List[int]]:
heapq.heapify(points)
closest_points = []
for i in range(k):
closest_points.append(heapq.heappop(points))
return closest_points
This should be O(N):
def k_closest_points(points: List[List[int]], k: int) → List[List[int]]:
heapq.heapify(points)
closest_points = []
for i in range(k):
closest_points.append(heapq.heappop(points))
return closest_points
Or possibly n+k (where n is the length of points since heapify is O(N))
leetcode
C# version test 2 seems bugged. It expects (-2, 2) as the first closest, but the one is the (1, 3). Distances are sqrt(4) and sqrt(3) respectively
Two errors in Alternative solution:
dist() does not need sqrt as square root preserves ordering
no need to reverse, the max of (-distance) is the smallest distance from the origin
^this
(1, 3)'s distance to (0, 0) is sqrt(10)
in a white boarding interview, you can casually mention we need to import these. in a online coding interview, you should be able to look it up
the dist(point) function should be -point[0] ** 2 - point[1] ** 2
Tulip is right. With heapify we can get the complexity down to O(n + k*log n)
Alternate solution seems better in terms of O complexity, time is the same (I saw different thoughts on this in comments, so to me it’s we still have to check every point and there is a chance they are bad sorted initially so that we’d have to insert each one in the heap which give n*log(N) though) but space gets reduced from O(N) to O(K), nice.
In the alternate version, should
return -point[0] ** 2 + point[1] ** 2
be
return -( point[0] ** 2 + point[1] ** 2 )
Getting the following error for C#:
Solution.cs(9,22): error CS0246: The type or namespace name `PriorityQueue’ could not be found. Are you missing an assembly reference?
using System;
using System.Collections.Generic;
using System.Linq;
class Solution
{
public static List<List<int>> KClosestPoints(List<List<int>> points, int k)
{
var pq = new PriorityQueue<List<int>,double>();
var point2 = new List<int>() {0,0};
foreach(var point1 in points)
{
var dist = FindDistance(point1, point2);
pq.Enqueue(point1,dist);
}
var ans = new List<List<int>>();
for(int i = 0; i < k; i++)
{
ans.Add(pq.Dequeue());
}
return ans;
}
public static double FindDistance(List<int> point1, List<int> point2)
{
var x = point1[0] - point2[0];
var y = point1[1] - point2[1];
var xsquare = Math.Pow(x, 2);
var ysquare = Math.Pow(y, 2);
return Math.Sqrt(xsquare + ysquare);
}
public static List<string> SplitWords(string s)
{
return string.IsNullOrEmpty(s) ? new List<string>() : s.Trim().Split(' ').ToList();
}
public static void Main()
{
int pointsLength = int.Parse(Console.ReadLine());
List<List<int>> points = new List<List<int>>();
for (int i = 0; i < pointsLength; i++)
{
points.Add(SplitWords(Console.ReadLine()).Select(int.Parse).ToList());
}
int k = int.Parse(Console.ReadLine());
List<List<int>> res = KClosestPoints(points, k);
foreach (List<int> row in res)
{
Console.WriteLine(String.Join(' ', row));
}
}
}
I think the time complexity can be O(n) + klog(n), where k might be big as n
The idea is that we already have the full list that we can simply use heapify
from typing import List
from heapq import heapify, heappop
def k_closest_points(points: List[List[int]], k: int) -> List[List[int]]:
if k >= len(points):
return sorted(points, key=lambda x: x[0]**2 + x[1] ** 2)
h = [(p[0]**2 + p[1]**2, p) for p in points]
heapify(h)
rst = []
assert h
for _ in range(k):
_, p = heappop(h)
rst.append(p)
return rst