1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
/**
------j---------K------
---------------K--j---
**/
class Solution {
private static final Random RANDOM = new Random();
public int[][] kClosest(int[][] points, int K) {
int lo = 0;
int hi = points.length - 1;
shuffle(points);
while (lo < hi) {
int j = partition(points, lo, hi);
if (j < K) {
lo = j + 1;
} else if (j > K) {
hi = j - 1;
} else {
return copyOf(points,K);
}
}
return copyOf(points, K);
}
int partition(int[][] a, int lo, int hi) {
int i = lo;
int j = hi + 1;
while (true) {
while (less(a[++i], a[lo])) {
if (i == hi) break;
}
while (less(a[lo], a[--j])) {
if (j == lo) break;
}
if (i >= j) break;
swap(a, i, j);
}
swap(a, lo, j);
return j;
}
static boolean less(int[] a, int[] b) {
int diff = b[0] * b[0] + b[1]*b[1] - a[0]* a[0] - a[1] * a[1];
return diff > 0;
}
void swap(int[][] a, int i, int j) {
int[] temp = a[i];
a[i] = a[j];
a[j] = temp;
}
static int[][] copyOf(int[][] points, int k) {
int[][] a = new int[k][];
for (int i = 0; i < k; i++) {
a[i] = points[i];
}
return a;
}
void shuffle(int[][] a) {
for (int i = 0; i < a.length; i++) {
swap(a, i, RANDOM.nextInt(a.length));
}
}
public int[][] kClosest2(int[][] points, int K) {
List<Point> sortedPoints = new ArrayList<>();
for (int i = 0 ; i < points.length; i++) {
sortedPoints.add(new Point(points[i][0], points[i][1]));
}
Collections.sort(sortedPoints);
int[][] res = new int[K][2];
for (int i = 0; i < Math.min(points.length, K); i++) {
res[i] = new int []{sortedPoints.get(i).x, sortedPoints.get(i).y};
}
return res;
}
class Point implements Comparable<Point> {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
public int compareTo(Point that) {
return
(this.x * this.x + this.y * this.y) -
(that.x * that.x + that.y * that.y)
;
}
public String toString() {
return String.format("[%d,%d]", this.x, this.y);
}
}
}
|