• 中位数和顺序统计学


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

    最小值是第1个顺序统计量(i=1)

    最大值是第n个顺序统计量(i=n)

    中位数:一个中位数(median)是它所在集合的“中点元素”,当n为奇数时,i=(n+1)/2,当n为偶数是,中位数总是出现在1 (下中位数)和2 (上中位数)。

    找最大值/最小值问题,通过比较n-1次可以得出结果。

    MINIMUM(A)
    1  minA[1]
    2  for i ← 2 to length[A]
    3         do if min > A[i]
    4                then minA[i]
    5  return min

    如果要同时找出最大值和最小值,则比较次数最少并不是2*n-2,而是3 ,我们可以将一对元素比较,然后把较大者于max比较,较小者与min比较,这样就只需要3

    如果是一般的选择问题,即找出一段序列第i小的数,看起来要比找最大值或最小值要麻烦,其实两种问题的渐进时间都是4

    首先看看这个强悍的伪代码:

    RANDOMIZED-SELECT(A, p, r, i)
    1  if p = r
    2      then return A[p]
    3  q ← RANDOMIZED-PARTITION(A, p, r)
    4  kq - p + 1
    5  if i = k          ▹ the pivot value is the answer
    6      then return A[q]
    7  elseif i < k
    8      then return RANDOMIZED-SELECT(A, p, q - 1, i)
    9  else return RANDOMIZED-SELECT(A, q + 1, r, i - k)

    这个算法利用了随机化的Partition算法,这个实在第七章的随机化快排中讲到:http://www.wutianqi.com/?p=2368,不记得的可以先复习下前面的快排。

    这个随机化的选择算法返回数组A[p..r]中第i小的元素。

    具体实现如下:

    template <class T>
    int randomPartition(T a[], int beg, int end)
    {
    //随机选取与end交换
    int randIndex = beg + rand() % (end - beg + 1);
    swap(a[randIndex], a[end]);

    //将end作为基准元素
    T posElem = a[end];
    int pos = beg - 1;

    //从beg扫描到end-1
    for (int i = beg; i < end; i++)
    {
    //将小于等于的元素交换到前面
    if (a[i] <= posElem && pos != i)
    {
    pos++;
    swap(a[i], a[pos]);
    }
    }

    //交换基准元素到分割点
    swap(a[pos + 1], a[end]);
    return pos + 1;
    }

    //随机选取递归版本
    template <class T>
    T randomSelect(T a[], int p, int r, int i)
    {
    if (p == r)
    return a[p];

    //随机划分
    int q = randomPartition(a, p, r);

    //划分后的左子序列个数
    int k = q - p + 1;

    //刚好划分到q==i为第i个最小数
    if (i == k)
    {
    return a[q];
    }

    //继续搜索左子序列
    else if (i < k)
    {
    return randomSelect(a, p, q - 1, i);
    }

    //继续搜索右子序列
    else
    return randomSelect(a, q + 1, r, i - k);
    }

    //随机选取迭代版本
    template <class T>
    T randomSelectUnrecursive(T a[], int p, int r, int i)
    {
    int q = 0, k = 0;
    while (p != r)
    {
    q = randomPartition(a, p, r);
    k = q - p + 1;
    if (i == k)
    {
    return a[q];
    }

    //与递归不同的是将搜索区间改变后循环即可
    else if (i < k)
    {
    r = q - 1;
    }
    else
    {
    p = q + 1;
    i = i - k;
    }
    }
    return a[p];
    }

    转自:http://www.cppblog.com/tanky-woo/archive/2011/04/26/145044.html

  • 相关阅读:
    数据结构和算法(Golang实现)(13)常见数据结构-可变长数组
    数据结构和算法(Golang实现)(5)简单入门Golang-接口
    数据结构和算法(Golang实现)(3)简单入门Golang-流程控制语句
    数据结构和算法(Golang实现)(4)简单入门Golang-结构体和方法
    分库分布的几件小事(一)数据库如何拆分
    分布式的几件小事(十二)分布式事务
    分布式的几件小事(十一)分布式session如何实现
    分布式的几件小事(十)分布式锁是啥
    分布式的几件小事(九)zookeeper都有哪些使用场景
    分布式的几件小事(八)分布式服务接口请求的顺序性如何保证
  • 原文地址:https://www.cnblogs.com/yysblog/p/2278089.html
Copyright © 2020-2023  润新知