import
java.util.*;
public
class
Main {
static
void
swap(ArrayList<Integer> arr,
int
a,
int
b) {
int
temp = arr.get(a);
arr.set(a, arr.get(b));
arr.set(b, temp);
}
static
int
partition(ArrayList<Integer> arr,
int
l,
int
r,
int
x) {
for
(
int
i = l; i < r; i++) {
if
(arr.get(i) == x) {
swap(arr, r, i);
break
;
}
}
x = arr.get(r);
int
i = l;
for
(
int
j = l; j < r; j++) {
if
(arr.get(j) <= x) {
swap(arr, i, j);
i++;
}
}
swap(arr, i, r);
return
i;
}
static
int
findMedian(ArrayList<Integer> arr,
int
l,
int
n) {
ArrayList<Integer> lis =
new
ArrayList<>();
for
(
int
i = l; i < l + n; i++) {
lis.add(arr.get(i));
}
Collections.sort(lis);
return
lis.get(n /
2
);
}
static
int
kthSmallest(ArrayList<Integer> arr,
int
l,
int
r,
int
k) {
if
(k >
0
&& k <= r - l +
1
) {
int
n = r - l +
1
;
ArrayList<Integer> median =
new
ArrayList<>();
int
i =
0
;
while
(i < n /
5
) {
median.add(findMedian(arr, l + i *
5
,
5
));
i++;
}
if
(i *
5
< n) {
median.add(findMedian(arr, l + i *
5
, n %
5
));
i++;
}
int
medOfMed;
if
(i ==
1
) {
medOfMed = median.get(i -
1
);
}
else
{
medOfMed = kthSmallest(median,
0
, i -
1
, i /
2
);
}
int
pos = partition(arr, l, r, medOfMed);
if
(pos - l == k -
1
) {
return
arr.get(pos);
}
if
(pos - l > k -
1
) {
return
kthSmallest(arr, l, pos -
1
, k);
}
return
kthSmallest(arr, pos +
1
, r, k - pos + l -
1
);
}
return
Integer.MAX_VALUE;
}
static
ArrayList<Integer> closestElements(ArrayList<Integer> arr,
int
k,
int
x) {
int
n = arr.size();
int
KthElem = kthSmallest(arr,
0
, n -
1
, k);
ArrayList<Integer> diff =
new
ArrayList<>();
HashMap<Integer, ArrayList<Integer>> maps =
new
HashMap<>();
for
(
int
elem : arr) {
int
temp = Math.abs(elem - KthElem);
maps.putIfAbsent(temp,
new
ArrayList<>());
maps.get(temp).add(elem);
diff.add(temp);
}
int
XthElem = kthSmallest(diff,
0
, n -
1
, x);
ArrayList<Integer> res =
new
ArrayList<>();
for
(
int
dx : diff) {
if
(dx <= XthElem) {
for
(
int
elem : maps.get(dx)) {
if
(res.size() < x) {
res.add(elem);
}
}
}
}
return
res;
}
public
static
void
main(String[] args) {
ArrayList<Integer> arr =
new
ArrayList<>(Arrays.asList(
1
,
2
,
3
,
4
,
10
,
15
));
int
k =
3
, x =
2
;
ArrayList<Integer> res = closestElements(arr, k, x);
Collections.sort(res);
for
(
int
i : res) {
System.out.print(i +
" "
);
}
}
}