线性求中位数 poj2388

在做uva11300时,遇到了n < 1000 000的中位数,就看了一下线性求中位数。

该算法的最差时间复杂度为O(N^2),期望时间复杂度为O(N),证明推理详见算法导论P110。

和快排的思想很像,同理,线性求第k大数,算法如下:

①以某个数x将一段数组分成两部分,比x小的放在左边,比x大的放在右边

②如果x刚好是出于要找的位置的,直接返回

③如果在x的左边,则递归在x的右边找

④如果在x的右边,则递归在x的左边找

代码如下:

 1 /*===============================================================
 2 *   Copyright (C) 2014 All rights reserved.
 3 *   
 4 *   File Name: poj2388.cpp
 5 *   Author:sunshine
 6 *   Created Time: 2014年07月28日
 7 *
 8 ================================================================*/
 9 #include <map>
10 #include <queue>
11 #include <stack>
12 #include <math.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <iostream>
16 #include <algorithm>
17 
18 using namespace std;
19 
20 
21 int find_mid(int arr[], int left, int right, int x){
22     if(left >= right){
23         return arr[left + x];
24     }
25     int mid = arr[left];
26     int i = left;
27     int j = right;
28     while(i < j){
29         while(i < j && arr[j] >= mid) j--;
30         arr[i] = arr[j];
31         while(i < j && arr[i] <= mid) i++;
32         arr[j] = arr[i];
33     }
34     arr[j] = mid;
35     if(i - left == x) return arr[i];
36     if(i - left < x) return find_mid(arr, i + 1, right, x - (i - left + 1));
37     else return find_mid(arr, left, i - 1, x);
38 }
39 
40 int arr[10005];
41 int main(){
42     int n;
43     while(scanf("%d", &n) != EOF){
44         for(int i = 0;i < n;i ++){
45             scanf("%d", &arr[i]);
46         }
47         printf("%d
", find_mid(arr, 0, n-1, n / 2));
48     }
49     return 0;
50 }
View Code
原文地址:https://www.cnblogs.com/-sunshine/p/3872482.html