자료구조 & 알고리즘/LeetCode

feat: [Med.] K Closest Points to Origin (JS/TS)

ha2el 2024. 6. 17. 01:00

https://leetcode.com/problems/k-closest-points-to-origin/description/

1. 문제분석
좌표평면 -> [x,y] 1~10,000개 points[], 정수 k -> [0,0] 기준 가장 가까운 점 부터 k개 리턴

2. 풀어보기
[[1,3],[-2,2]], 1개 -> [1^2+3^2,(-2)^2+2^2] -> [10,8] -> [1,3] 리턴

3. 슈도코드
points[] 돌려서 -> 우선순위큐에 넣는데, comparator를 거리공식 사용 (루트 생략)

4. 구현코드

type Point = [number, number];

const by_distance_asc = ([x1, y1]: Point, [x2, y2]: Point) => x1 ** 2 + y1 ** 2 < x2 ** 2 + y2 ** 2;

const kClosest = (points: Point[], k: number): Point[] => {
  if (points.length === k) {
    return points;
  }

  return by_array(points, k);
  // return by_heap(points, k);
};

const by_array = (points: Point[], k: number): Point[] => {
  points.sort((a, b) => (by_distance_asc(a, b) ? -1 : 1)); // result set의 유니크가 보장됨

  return points.slice(0, k);
};

const by_heap = (points: Point[], k: number) => {
  const result: Point[] = [];
  const heap = new Heap<Point>(by_distance_asc, points);

  for (let i = 0; i < k; i++) {
    result.push(heap.pop()!); // 문제에서 k <= points.length 보장됨
  }

  return result;
};

class Heap<T>; // 힙 구현은 https://ha2el.tistory.com/23 참고


5. 풀이회고
힙에 comparator 정의해서 입력좌표 다 넣고, k개 빼기만 하면 되는 아주 간단한 문제였다.

기본적인 문제지만, 책에도 있고 Glind75에도 있는 것 보니 핵심적인 유형인 것 같다. 항상 기본이 제일 중요하다.

그리고 나는 당연히 힙만 생각했는데, Solutions를 보니 그냥 배열 정렬해서 k개 잘라 뱉는 코드도 있었다.

실제로 돌려보니 오히려 이 쪽이 힙 보다 더 빨랐다. 오퍼레이션이 더 간단해서 그런 듯.