线性求中位数 poj2388

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

和快排的思想很像,同理,线性求第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\n", find_mid(arr, 0, n-1, n / 2));
48     }
49     return 0;
50 }

线性求中位数 poj2388

时间: 2024-10-24 19:04:41

线性求中位数 poj2388的相关文章

URAL 1306 - Sequence Median 小内存求中位数

[题意]给出n(1~250000)个数(int以内),求中位数 [题解]一开始直接sort,发现MLE,才发现内存限制1024k,那么就不能开int[250000]的数组了(4*250000=1,000,000大约就是1M内存). 后来发现可以使用长度为n/2+1的优先队列,即包含前一半的数以及中位数,其他数在读入的时候就剔除,这样可以省一半的空间. 1 #include<bits/stdc++.h> 2 #define eps 1e-9 3 #define FOR(i,j,k) for(in

POJ 2388 Who&#39;s in the Middle(水~奇数个数排序求中位数)

题目链接:http://poj.org/problem?id=2388 题目大意: 奇数个数排序求中位数 解题思路:看代码吧! AC Code: 1 #include<stdio.h> 2 #include<algorithm> 3 using namespace std; 4 int main() 5 { 6 int n; 7 while(scanf("%d",&n)!=EOF) 8 { 9 int na[n+1]; 10 for(int i=0; i

线性求逆元

简介 逆元,简单的来说就是a?b≡1(modp),那么b就是a关于p的逆元. 正常的来说用扩展欧几里得来做.复杂度不是线性的. 但是如果所有的i≤p,有一个线性求逆元的方法. 正常的来说 方法 因为i≤p,所以考虑用i来表示p,并要求表示出来的所有数都能用p和i表示. 设p=ki+b,k=?pi?,l=pmodi 那么ki+b≡0(modp) 因为要求的是i?1,所以需要把i?1独立起来,所以我们等式两边同时乘以i?1b?1 那么式子就可以变成kb?1+i?1≡0 然后把可以求得i的逆元的数放到

求中位数

求中位数 题目描述 输入n和n个数,求大于中位数的数据个数.(n小于50) 中位数是把一列数从小到大排列后,中间的那个数!如果那一列数是偶数,就取中间两个数的平均数! 例如: 第1组数:1.2.3.6.7的中位数是3. 第2组数:1.2.3.5的中位数是2.5. 输入描述 输入正整数n和n个实数 输出描述 1.输出中位数保留小数1位.中位数输出占一行. 2.输出大于中位数的数据个数占一行. 样例输入 4 1 2 3 5 样例输出 2.5 2

POJ 3784 Running Median 动态求中位数 堆

题意. 1000个case 每个case 输入若干个数,对第k个输入,如果k为奇数,则输出前k个数的中位数 那么这就是动态求中位数了 实现的思路也比较简洁 用两个堆, 大顶堆和小顶堆 每次输入一个数,如果这个数比当前的中位数大,就存入小顶堆中,  否则就存入大顶堆. 然后调整, 小顶堆元素的个数要等于大顶堆的元素个数,或者比其多1. 如果小顶堆的元素太多,就塞到大顶堆里,反之亦然 这样一来就会发现.小顶堆的元素比所有大顶堆的元素都大, 而且小顶堆的堆顶就是中位数. 那么怎么样才能想到这样一个思路

双堆求中位数

堆 堆的动态创建与删除可参考 http://www.java3z.com/cwbwebhome/article/article1/1362.html?id=4745,此处不再赘述. 双堆求中位数 算法描述: 1.创建两个堆(一个小根堆.一个大根堆),堆大小至少为给定数据个数的一半,向上取整: 2.假定变量mid用来保存中位数,取定第一个元素,赋值给mid,即作为初始的中位数: 3.依次遍历后面的每一个数据,如果比mid小,则插入大根堆:否则插入小根堆: 4.如果大根堆和小根堆上的数据个数相差为2

在线求中位数

在线求第k个数做得多了,在线求中位数也是用堆,一个最大堆,一个最小堆. 思想大概是这样子的: 一个最大堆,一个最小堆,最大堆对应于前n/(n+1)个数,最小堆对应于后n/n+1个数:假设最大堆堆项元素为n1, 最小堆堆顶为n2, 则n1 <= n2; 确保两个堆的大小最多只差1. 设最大堆大小为s1, 最小堆大小为s2,则abs(s1-s2) <= 1: 对于新来的数m,分情况调整: 如果s1== s2, 那么:如果m<= n2, m插入到最大堆,s1= s1+1; 否则插入到最小堆,s

LeetCode题目----求中位数---标签:Array

题目难度---困难 题目要求: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个有序数组的中位数.要求算法的时间复杂度为 O(log (m+n)) . 思路:第一眼看到题目两个数组求中位数,看似很复杂,但是仔细一想,两个数组合在一块不久行了?然后合并后的数组给他排序,进而判断是奇数位数组还是偶数位数组 ok!代码奉上: public static double findMedianSortedArrays(int[] nums1, int[] nums2) {

线性求逆元推导

本篇介绍线性求逆元的推导过程 ·对于一个质数\(P\),我们需要求出\(1-N\)在\(mod\ P\)意义下的逆元,如何使用线性的方法求其逆元呢? ·首先,我们设\(t=P/i,k=P%i\); ·对于\(i*t+k≡0 \pmod{P}\),我们可以做出如下推导: ·等式两边同时除以\(i*k\),我们可以得到新式子\(\frac{t}{k}+\frac{1}{i}≡0 \pmod{P}\); ·从而得到:\(\frac{P}{i}*inv[P\%i]+inv[i]≡0 \pmod{P}\)