2018-10-20 K Closest Points [M]

  1. K Closest Points
    Given some points and an origin point in two-dimensional space, find k points which are nearest to the origin.
    Return these points sorted by distance, if they are same in distance, sorted by the x-axis, and if they are same in the x-axis, sorted by y-axis.

Example
Given points = [[4,6],[4,7],[4,4],[2,5],[1,1]], origin = [0, 0], k = 3
return [[1,1],[2,5],[4,4]]

"""
Definition for a point.
class Point:
    def __init__(self, a=0, b=0):
        self.x = a
        self.y = b
"""

import heapq

class Solution:
    """
    @param points: a list of points
    @param origin: a point
    @param k: An integer
    @return: the k closest points
    """
    def kClosest(self, points, origin, k):
        heap = []
        for p in points:
            dist = self.get_dist(p, origin)
            # put a tuple into heap queue
            heapq.heappush(heap, (-dist, -p.x, -p.y))
            if len(heap) > k:
                heapq.heappop(heap)
        
        heap.sort(reverse=True)
        return [Point(-x,-y) for (_, x, y) in heap]
        
    def get_dist(self, p, o):
        return (p.x - o.x)**2 + (p.y - o.y)**2

Notes:

  1. Python (min) heap queue (priority queue)
    Use heap queue to further optimize time complexity from O(nlogn) for sort to O(nlogk)
import heapq // cannot be placed in class
heap = []
heapq.heappush(heap, item)

Use negative sign to make reverse sorting (from min priority to max heap)

It even just needs one line, but time complexity is O(nlogn).

import nsmallest
return heapq.nsmallest(k, points, key=lambda p: [(p.x-o.x)**2 + (p.y-o.y)**2, p.x])
  1. Define sort/heapify function
  • item for heap queue:
  • key for sort list

The operator module functions allow multiple levels of sorting. This takes advantage of python. Even though it is not "expected" by interviewers (they expect a comparator), it at least helps solve problems!

>>> student_objects = [
        Student('john', 'A', 15),
        Student('jane', 'B', 12),
        Student('dave', 'B', 10),
]

>>> sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
  1. Do not use x^2 to represent. Use x**2 instead. Because ^ means bitwise XOR.
    "Each bit position in the result is the logical XOR of the bits in the corresponding position of the operands. (1 if the bits in the operands are different, 0 if they are the same.)"

  2. Construct a comparator:
    If Point 2 cannot be used here, I will use a new Type to represent tuple (-dist, -p.x, -p.y)

class Type:
    def __init__(self, dist, point):
        self.dist = dist
        self.point = point

    def cmp(self, other):
        if other.dist != self.dist:
            return other.dist - self.dist
        if other.point.x != self.point.x:
            return other.point.x - self.point.x
        return other.point.y - self.point.y

    def __lt__(self, other):
        return self.cmp(other) < 0
    def __gt__(self, other):
        return self.cmp(other) > 0
    def __eq__(self, other):
        return self.cmp(other) == 0

The take away is to how write cmp() in this problem. To compare point and other, __lt__(self, other) means point < other.

你可能感兴趣的:(2018-10-20 K Closest Points [M])