求无序数组的中位数

中位数即是排过序后的处于数组最中间的元素。 不考虑数组长度为偶数的情况。设集合元素个数为n。

简单的想了下:
思路1) 把无序数组排好序,取出中间的元素
            时间复杂度 采用普通的比较排序法 O(N*logN)
            如果采用非比较的计数排序等方法, 时间复杂度 O(N), 空间复杂度也是O(N).

思路2) 
          2.1)将前(n+1)/2个元素调整为一个小顶堆,
          2.2)对后续的每一个元素,和堆顶比较,如果小于等于堆顶,丢弃之,取下一个元素。 如果大于堆顶,用该元素取代堆顶,调整堆,取下一元素。重复2.2步           
          2.3)  当遍历完所有元素之后,堆顶即是中位数。

思路3) 熟话说,想让算法跑的更快,用分治!
            快速排序之所以得名"快排",绝非浪得虚名!因为快排就是一种分治排序法!
            同样,找中位数也可以用快排分治的思想。具体如下:
            任意挑一个元素,以改元素为支点,划分集合为两部分,如果左侧集合长度恰为 (n-1)/2,那么支点恰为中位数。如果左侧长度<(n-1)/2, 那么中位点在右侧,反之,中位数在左侧。 进入相应的一侧继续寻找中位点。
            这种方法很快,但是在最坏的情况下时间复杂度为O(N^2), 不过平均时间复杂度好像是O(N)。

思路4) 快排的方法存在不确定性,导致其最坏和最好的时候差别很大, 那么有没有一种确定性的方法呢? 答案是有的
            貌似算法导论里有讲到. 这里我就先不深究了, 可以参考如下的文章, 
            O(n)时间快速选择
            http://www.shadowxh.com/?p=598
            以及本文的别人的评论

引申一:
查找N个元素中的第K个小的元素(来自编程珠玑)

编程珠玑给出了一个时间复杂度O(N),的解决方案。该方案改编自快速排序。
经过快排的一次划分,
   1)如果左半部份的长度>K-1,那么这个元素就肯定在左半部份了
   2)如果左半部份的长度==K-1,那么当前划分元素就是结果了。
   3)如果。。。。。。。<K-1,那么这个元素就肯定在右半部分了。
  并且,该方法可以用尾递归实现。效率更高。

时间复杂度分析, 由于差不多每次都是把序列划分为一半。。。假设划分的元素做了随机优化,时间复杂度近似于
N+N/2+N/4.... = 2N*(1-2^-(logN)) 当N较大时 约等于 2N 也就是 O(N)。

看来,快速排需的用处可大着咧。。。

也用来查找可以N个元素中的前K个小的元素,前K个大的元素。。。。等等。

引申二:
查找N个元素中的第K个小的元素,假设内存受限,仅能容下K/4个元素。
分趟查找,
第一趟,用堆方法查找最小的K/4个小的元素,同时记录剩下的N-K/4个元素到外部文件。
第二趟,用堆方法从第一趟筛选出的N-K/4个元素中查找K/4个小的元素,同时记录剩下的N-K/2个元素到外部文件。
。。。
第四趟,用堆方法从第一趟筛选出的N-K/3个元素中查找K/4个小的元素,这是的第K/4小的元素即使所求。

时间: 2024-08-25 18:13:13

求无序数组的中位数的相关文章

无序数组的中位数

参考:http://mp.weixin.qq.com/s?__biz=MjM5ODIzNDQ3Mw%3D%3D&idx=1&mid=2649965551&scene=0&sn=bc769eb3fbd2f4075c58524f4cc8332d 中位数,就是数组排序后处于数组最中间的那个元素.说来有些麻烦,如果数组长度是奇数,最中间就是位置为(n+1)/2的那个元素.如果是偶数呢,标准的定义是位置为n/2和位置为n/2+1的两个元素的和除以2的结果,有些复杂.为了解答的方便,我

78 无序数组的中位数

[本文链接] http://www.cnblogs.com/hellogiser/p/median-of-unsorted-array.html [题目] 中位数即是排过序后的处于数组最中间的元素. 不考虑数组长度为偶数的情况.设集合元素个数为n. [分析] 大体思路:思路1) 排序法 n*lgn 把无序数组排好序,取出中间的元素            时间复杂度 采用普通的比较排序法 O(N*logN)            如果采用非比较的计数排序等方法, 时间复杂度 O(N), 空间复杂度

求无序数组最大差值

hulu的一道面试题,比如你预先知道股票的每天的股价,让你算出哪一天买入 哪一天卖出赚的最多. 这个可以变形为找出一个无序数组中后面的数减去前面的数的最大值. 简单粗暴的解法就是遍历了 复杂度O(n^2) 这其实是个很典型的DP问题,复杂度O(n). 转换公式是这样的: S0 = 0 Sn =  Tn > 0 ? Tn : 0  (Tn = an -  an-1 + Sn-1) 伪代码: MinIdx = 0 MaxIdx = 0 S[0] = 0 MaxR = INTMIN FOR i IN

【桶排序】求无序数组中最大的“Gap&quot;

题目:leetcode Given an unsorted array, find the maximum difference between the successive elements in its sorted form. Try to solve it in linear time/space. Return 0 if the array contains less than 2 elements. You may assume all elements in the array a

求无序数组中未出现的最小正整数

给定一个无序整型数组arr,找到数组中未出现的最小正整数.要求时间复杂度为O(N),空间复杂度为常数级. 例如: arr=[33,33,33,33]  返回1 arr=[34,56,45,12]  返回1 arr=[-1,2,3,4]  返回1 arr=[1,2,3,4]   返回5 ... 随便什么都行 原理很简单,代码用数据跑一遍就看出思想了. 1 #include<iostream> 2 #include<fstream> 3 using namespace std; 4 i

无序数组的中位数(set+deque)hdu5249

KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 901    Accepted Submission(s): 398 Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度.数十亿的请求被推到一个大管道后同时服务从管头拉取请求.让我们来定义每个请求都有一个重要值.我的K

求一无序数组中第n大的数字 - 快速选择算法

逛别人博客的时候,偶然看到这一算法题,顺便用C++实现了一下. 最朴素的解法就是先对数组进行排序,返回第n个数即可.. 下面代码中用的是快速选择算法(不晓得这名字对不对) 1 #include <vector> 2 #include <iostream> 3 #include <stdexcept> 4 #include <cstdio> 5 6 const int QS_EERRMSG_LEN = 256; 7 8 9 /** 10 * 快速选择求无序数组

求两个数组的中位数

package kpp.base; /** * 求两个有序数组的中位数 * 此代码适用于两个数组长度不等的情况 * @author kpp * */ public class TwoArrayMedian { public static void main(String[] args) { // TODO Auto-generated method stub float a[] = {1,2,3,4}; //float b[] = {2,3,4,5,8,9,10}; float b[] = {8

在O(n)时间复杂度内求无序数组中任意两个元素的最大差值,以及存在的组数

题目描述: 求无序数组中任意两个元素的最大差值,以及存在最大差值的组别数. 输入: 输入包含两行,第一行输入一个整数n:第二行n个正整数,用空格隔开. 输出: 输出为一行,包含最大差值,以及存在组别数. 样例输入: 4 4  1  2  1 输出: 3  2 一种实现代码如下(Java版): 1 import java.util.Scanner; 2 /** 3 * 在O(n)时间复杂度内求无序数组中任意两个元素的最大差值,以及存在的组数 4 * @author JiaJoa 5 * 6 */