本文共 2451 字,大约阅读时间需要 8 分钟。
设计一个算法快速计算无序数列的中位数,时间复杂度为O(n)。
中位数的定义为:若数列元素个数为奇数,则为排序后中间的数;若为偶数,则为中间两个数的平均值。常规排序方法时间复杂度为O(n log n),但我们需要线性时间解决方案。快速选择算法(Quick Select)可满足这一需求,因为其平均时间复杂度为O(n)。
快速选择算法:
平衡性考虑:
处理边界情况:
import java.util.Scanner;public class zhongweishu { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int n = sc.nextInt(); int[] a = new int[n]; for (int i = 0; i < n; i++) { a[i] = sc.nextInt(); } if (n % 2 != 0) { int p = quickSelect(a, 0, n - 1, (n + 1) / 2); System.out.println(p); } else { int mid1 = quickSelect(a, 0, n - 1, n / 2); int mid2 = quickSelect(a, 0, n - 1, n / 2 + 1); double avg = (mid1 + mid2) / 2.0; System.out.printf("%.3f", avg); } } } private static int quickSelect(int[] a, int left, int right, int k) { if (left == right) { return a[left]; } int pivot = ((new Random()).nextInt(right - left + 1) + left); int temp = a[pivot]; a[pivot] = a[left]; a[left] = temp; int i = left + 1; int j = right; while (i < j) { if (a[i] > a[j]) { if (i != left + 1) { a[pivot] = a[i]; a[i] = a[left]; a[left] = a[right]; a[right] = a[pivot]; pivot = left; } a[right] = a[j]; a[j] = a[right]; j--; } else { if (j != right) { a[pivot] = a[j]; a[j] = a[right]; a[right] = a[pivot]; pivot = right; } a[right] = a[i]; a[i] = a[right]; i++; } } if (pivot < k) { return quickSelect(a, pivot + 1, right, k); } else { return quickSelect(a, left, pivot - 1, k); } }}
这种方法确保了在线性时间内找到数列的中位数,适用于大规模数据处理。通过合理的分割策略,算法在各个情况下均能有效运行。
转载地址:http://nmkqz.baihongyu.com/