中位数和顺序统计学

Published: 17 Sep 2011 Category:

在一个由n个元素组成的集合中,第i个顺序统计量是该集合中第i小的元素。

一个中位数是它所在集合的"中点元素"。当n为奇数,中位数出现在i=(n+1)/2处;当n为偶数,存在两个中位数,i=n/2和i=n/2+1。如果不考虑奇偶性,中位数出现在$$\lfloor(n+1)/2\rfloor$$处(下中位数)和$$\lceil(n+1)/2\rceil$$处(上中位数)。

形式化地定义选择问题:

输入:一个包含n个(不同的)数的集合A和一个数i,$$1\le i\le n$$。

输出:元素$$x\in A$$,它恰大于A中其他的i-1个元素。

最小值和最大值

在一个有n个元素的集合中,要通过n-1次比较才能找到最小值或最大值。

如果同时找出最小值和最大值,则可以成对的处理元素,将一对输入元素进行比较,将较小者与当前最小值进行比较,将较大者与当前最大值进行比较,即每两个元素需要3次比较。这种情况下需要的比较次数是$$3\lfloor n/2\rfloor$$处(下中位数)

一般选择问题

一般选择问题和找最小值的运行时间是相同的,都是$$\Theta(n)$$。基于快速排序算法的RANDOMIZED-SELECT算法,对输入数组进行递归划分,然后处理划分的一边。

RANDOMIZED-SELECT Java实现

[code lang=”java”]public class RandomizedSelect{ public static int randomizedPartition(int[] A, int p, int r){ int s = (int)Math.ceil(Math.random() * (r - p)) + p; int temp = A[r]; A[r] = A[s]; A[s] = temp; int x = A[r]; int i = p - 1; for(int j = p; j < r; j++){ if(A[j] <= x){ i++; temp = A[j]; A[j] = A[i]; A[i] = temp; } } i++; A[r] = A[i]; A[i] = x; return i; }

public static int randomizedSelect(int[] A, int p, int r, int i){
	if(p == r){
		return A[p];
	}
	int q = randomizedPartition(A, p, r);
	int k = q - p + 1;
	if(i == k){
		return A[q];
	} else if(i &lt; k){
		return randomizedSelect(A, p, q - 1, i);
	} else{
		return randomizedSelect(A, q + 1, r, i - k);
	}
}

public static void main(String[] args){
	int[] array = {3, 2, 6, 1, 9, 7, 8, 5, 4};
	for(int i : array){
		System.out.print(i + &quot;,&quot;);
	}
	System.out.print(&quot;\n&quot;);
	System.out.println(&quot;The i-th number:&quot; + randomizedSelect(array, 0, array.length - 1, 5));
} } [/code]

算法复杂度

在最坏情况下,每次划分过程中都按照余下的元素中最大的进行划分,则运行时间为$$\Theta(n^2)$$。在平均情况下,运行时间为$$\Theta(n)$$。即平均情况下,任何顺序统计量都可以在线性时间内得到。