題目描述
給定一個擁有奇數數量元素的陣列,你能夠在陣列整個排序好之前就找出它的中位數(中間值)嗎?
原題網址
輸入格式
輸入第一行為一個整數n,且為奇數,範圍在1到1000001之間(包含1和1000001)。
第二行為n個用空格分隔的整數,範圍在-10000到10000之間(包含-10000和10000),不會重複。
輸出格式
輸出只會有一個整數,那就是這個陣列的中位數。
範例輸入
7
0 1 2 4 6 5 3
0 1 2 4 6 5 3
範例輸出
3
解題概念
參考這篇文章,學習快速選擇法:
由於輸入的陣列元素皆不重複,因此中位數的元素索引位置即為陣列長度的一半。也就是說,利用快速選擇演算法,找出第「陣列長度一半」小的元素,就是題目要的輸出結果了。
參考答案
import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;
public class Solution {
// Complete the findMedian function below.
static int findMedian(int[] arr) {
int index = arr.length / 2;
int s = 0;
int e = arr.length - 1;
while (true) {
if (s == e) {
return arr[s];
}
final int x = arr[s]; // pivot
int l = s + 1;
int r = e;
while (true) {
while (r > s && arr[r] >= x) {
--r;
}
while (l <= r && arr[l] <= x) {
++l;
}
if (l < r) {
final int buffer = arr[l];
arr[l] = arr[r];
arr[r] = buffer;
} else {
if (r > s) {
final int buffer = arr[r];
arr[r] = arr[s];
arr[s] = buffer;
}
break;
}
}
if (index == r) {
return arr[index];
} else if (index < r) {
e = r - 1;
} else {
s = r + 1;
}
}
}
private static final Scanner scanner = new Scanner(System.in);
public static void main(String[] args) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));
int n = scanner.nextInt();
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(n);
int[] arr = new int[n];
String[] arrItems = scanner.nextLine().split(" ");
scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
for (int i = 0; i < n; i++) {
int arrItem = Integer.parseInt(arrItems[i]);
arr[i] = arrItem;
System.out.println(i);
}
int result = findMedian(arr);
bufferedWriter.write(String.valueOf(result));
bufferedWriter.newLine();
bufferedWriter.close();
scanner.close();
}
}