无序数组中位数

(1) 最小堆算法

首先将数组的前(n+1)/2个元素建立一个最小堆。

然后,对于下一个元素,和堆顶的元素比较,如果小于等于,丢弃之,接着看下一个元素。如果大于,则用该元素取代堆顶,再调整堆,接着看下一个元素。重复这个步骤,直到数组为空。

当数组都遍历完了,那么,堆顶的元素即是中位数。

 1 #include "stdafx.h"
 2 #include <iostream>
 3 using namespace std;
 4
 5 const int MAX_SIZE = 100;
 6
 7 class SmallHeap {
 8
 9 public:
10     SmallHeap() {
11         size = 0;
12     }
13
14     void add(int val) {
15         if (size >= MAX_SIZE)
16             return;
17
18         int s = size++;
19         shiftup(s, val);
20     }
21
22     int peek() {
23         return queue[0];
24     }
25
26     int poll() {
27         if (size <= 0)
28             return -1;
29
30         int ret = queue[0];
31         int s = --size;
32         shiftdown(0, queue[s]);
33         queue[s] = 0;
34         return ret;
35     }
36
37     void shiftup(int s, int val) {
38         while (s > 0) {
39             int parent = (s - 1) / 2;
40             if (queue[parent] < val) {
41                 break;
42             }
43             queue[s] = queue[parent];
44             s = parent;
45
46         }
47         queue[s] = val;
48     }
49
50     void shiftdown(int i, int val) {
51         int half = size / 2;
52         while (i < half) {
53             int child = 2 * i + 1;
54             int right = child + 1;
55             if (right < size && queue[child] > queue[right]) {
56                 child = right;
57             }
58             if (val < queue[child]) {
59                 break;
60             }
61             queue[i] = queue[child];
62             i = child;
63         }
64
65         queue[i] = val;
66     }
67
68 private:
69     int queue[MAX_SIZE];
70     int size;
71
72 };
73
74 int main()
75 {
76     int a[] = {5, 3, 8, 6, 4};
77     int length = sizeof(a) / sizeof(a[0]);
78     int halfLength = length / 2 + 1;
79
80     SmallHeap* heap = new SmallHeap();
81     for (int i = 0; i < halfLength; ++i) {
82         heap->add(a[i]);
83     }
84     for (int i = halfLength; i < length; ++i) {
85         if (heap->peek() < a[i])
86         {
87             heap->poll();
88             heap->add(a[i]);
89         }
90     }
91
92     cout << heap->peek() << endl;
93
94     int i;
95     cin >> i;
96
97     return 0;
98 }

(2) 快排的分而治之

任意挑一个元素,以该元素为支点,将数组分成两部分,左部分是小于等于支点的,右部分是大于支点的。如果你运气好,左部分正好是(n-1)/2个元素,那么支点的那个数就是中位数。否则的话,再找某一边继续排

 1 #include "stdafx.h"
 2 #include <iostream>
 3 using namespace std;
 4
 5 void swap(int a[], int i, int j) {
 6     int temp = a[i];
 7     a[i] = a[j];
 8     a[j] = temp;
 9 }
10
11 int partition(int arr[], int low, int high) {
12     int pivot = arr[low];
13     int i = low, j = high;
14     while (i <= j) {
15         while (i <= j && arr[i] <= pivot)i++;
16         while (i <= j && arr[j] >= pivot)j--;
17         swap(arr, i, j);
18     }
19     swap(arr, low, j);
20     return j;
21 }
22
23 int findMedian(int arr[], int k, int low, int high) {
24     if (k > high - low + 1) return -1;
25     int pos = partition(arr, low, high);
26     if (pos - low < k - 1) {
27         return findMedian(arr, k - pos - 1, pos + 1, high);
28     }
29     else if (pos - low == k - 1) {
30         return arr[pos];
31     }
32     else {
33         return findMedian(arr, k, low, pos - 1);
34     }
35 }
36
37 int main()
38 {
39     int arr[] = { 3,5,2,3,5,9,1,2,11,12,13 };
40     int length = sizeof(arr) / sizeof(arr[0]);
41     int res = 0;
42     if (length % 2 == 1) {
43         res = findMedian(arr, (length + 1) / 2, 0, length - 1);
44     }
45     else {
46         res = findMedian(arr, length / 2, 0, length - 1);
47     }
48     cout << res << endl;
49
50     int i;
51     cin >> i;
52
53     return 0;
54 }

时间: 2024-10-05 06:22:13

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

求无序数组的中位数

中位数即是排过序后的处于数组最中间的元素. 不考虑数组长度为偶数的情况.设集合元素个数为n. 简单的想了下:思路1) 把无序数组排好序,取出中间的元素            时间复杂度 采用普通的比较排序法 O(N*logN)            如果采用非比较的计数排序等方法, 时间复杂度 O(N), 空间复杂度也是O(N). 思路2)           2.1)将前(n+1)/2个元素调整为一个小顶堆,          2.2)对后续的每一个元素,和堆顶比较,如果小于等于堆顶,丢弃之,

78 无序数组的中位数

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

无序数组的中位数

参考: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的结果,有些复杂.为了解答的方便,我

有序和无序数组的二分搜索算法

题目意思 1.给定有序数组A和关键字key,判断A中是否存在key,如果存在则返回下标值,不存在则返回-1. 2.给定无序数组A和关键字key,判断A中是否存在key,如果存在则返回1,不存在则返回0. 对于1.2问题,我们都可以简单的写出O(n)的从头到尾为的扫描算法,这里就不在累赘,这里我们讨论的是基于二分查找的算法,使其时间在渐进意义上达到O(logn). 对于有序的数组,很"容易"写出基于二分的函数. 那么问题2,对于无序数组,怎么查找呢?这里我们用到了快速排序的划分原则.算法

求一无序数组中第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 * 快速选择求无序数组

求无序数组最大差值

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

快速查找无序数组中的第K大数?

1.题目分析: 查找无序数组中的第K大数,直观感觉便是先排好序再找到下标为K-1的元素,时间复杂度O(NlgN).在此,我们想探索是否存在时间复杂度 < O(NlgN),而且近似等于O(N)的高效算法. 还记得我们快速排序的思想麽?通过“partition”递归划分前后部分.在本问题求解策略中,基于快排的划分函数可以利用“夹击法”,不断从原来的区间[0,n-1]向中间搜索第k大的数,大概搜索方向见下图: 2.参考代码: 1 #include <cstdio> 2 3 #define sw

无序数组同时查找最大和最小的元素

在无序数组中查找最大或者最小的元素都需要进行n次比较,但是同时查找最大和最小的元素却可以在3n/2次比较内实现. 问题:给定一个长度为n的无序序列,同时查找出这个序列中的最大和最小值. 算法设计:如果只是在无序序列中查找最大或最小值,至少需要n-1次比较,但是同时查找出最大值和最小值却不需要2(n-1)次比较,而只需要3n/2次比较.其策略是:同时保存当前得到的最大值和最小值,之后依次从无序序列中取出两个数并进行比较,其中较小的一个与当前的最小值比较,较大的一个于当前的最大值比较,然后更新当前的

无序数组a,求a[i]-a[j]的最大值,且i&lt;j

一道面试题:对于无序数组a,求a[i]-a[j]的最大值,其中i<j 1 package test; 2 3 import java.util.Arrays; 4 5 public class FindMax { 6 public static void main(String[] args) { 7 int[] a = new int[] { 9, 20, 3, 16, 6, 5, 7, 1 }; 8 System.out.println("a[" + a.length + &