(转)算法导论—中位数与顺序统计量

http://m.blog.csdn.net/blog/zhangzhengyi03539

http://m.blog.csdn.net/blog/zhangzhengyi03539/46795831

一、选择最大值或者最小值的最优算法 
对于长度为n的数组,已证找最大值或者最小值比较操作下界就是n-1。所以只需要让第一个值为初始最大值或者初始最小值,用所有的值与这个值比较,更新这个值即可。

def minimum(a):
    minNum=a[0]
    for i in range(1,len(a)):
        if minNum>a[i]:
            minNum=a[i]
    return minNum
print(minimum ([1,2,3,4,5,6,7,8,9]))

二、同时选择最大值和最小值的快速算法(成对比较) 
首先设置一对初始的最大值最小值(总数个数是奇数,初始最大值最小值为第一个数,若是偶数就为前两个比较),然后剩下的数两两组对,对内比较大小,然后小的与当前最小的比,大的与当前最大的比。这样的话两个数需要比较三次。如果选择分别计算最大值最小值需要2(n-1)次比较,采用成对比较的话只需要3int(n/2)次

def minmax(a):
    k=len(a)
    if k%2==0:
        if a[0]<a[1]:
            minNum,maxNum=a[0],a[1]
        else:
            minNum,maxNum=a[1],a[0]
    else:
        minNum,maxNum=a[0],a[0]
    for i in range(2-k%2,k,2):
        if a[i]>a[i+1]:
            a[i+1],a[i]=a[i],a[i+1]
        if a[i]<minNum:
            minNum=a[i]
        if a[i+1]>maxNum:
            maxNum=a[i+1]
    return minNum,maxNum
print(minmax([1,2,3,4,5,6,7,8,9]))

三、期望时间为线性时间的选择算法—随机选择 
回想一下,快速排序的时候,选择一个数(随机)为基准,左右交换将小于基准的分到左边,大于基准的分到右边的思想,然后得到这个数在数组中的位置,这样我们可以根据这个位置判断我们要的数所处的位置,逐步缩小搜索范围。 
基于快速排序的舍弃法,不考虑直接命中的情况的话一次平均舍弃一半的数。

import random

def randomizedPartion(a,p,r):
    k=random.randint(p, r)
    a[k],a[r]=a[r],a[k]
    value=a[r]
    i=p-1
    for j in range(p,r):
        if a[j]<value:
            i+=1
            a[i],a[j]=a[j],a[i]
    i+=1
    a[i],a[r]=a[r],a[i]
    return i

def randomizedSelect(a,p,r,i):
    q=randomizedPartion(a,p,r)
    k=q-p+1
    if k==i:
        return a[q]
    else:
        if i<k:
            return randomizedSelect(a,p,q-1,i)
        else:
            return randomizedSelect(a,q+1,r,i-k)

lst=[2,6,3,1,5,0,7,8,4,9]
k=randomizedSelect(lst,0,len(lst)-1,10)
print(k)

四、最坏时间为线性时间的选择算法—中位数的中位数划分 
select算法的思想为:首先对数组中所有的数分组,然后计算每个组的中位数,然后计算所有组的中位数的中位数,然后把快速排序划分策略修改为按值划分,并且返回中位数的中位数在数组中位置。然后就可以判断舍弃了。 
基于中位数的中位数一次舍弃的数有下限n/4(这个是我自己算的一个下限,下确界可能更高点)——比如要找的数小于中位数的中位数,组里面的中位数大于中位数的中位数的那些组上半部分是肯定这一轮需要舍弃的,而这个的一个下线就是n/4,这样每次最多保存上一次数据的3n/4个数据,而每一次长度为n的计算量为theta(n),根据等比数列性质,它的阶数是跟首项同阶的。所以最坏情况的计算时间为theta(n)。

def midNum(a):
    k=len(a)
    groupNum=5
    start=0
    while start<k:
        end=min(k-1,start+4)
        InsertSort(a,start,end)
        start+=5
    if k<5:
        return a[(k-1)//2]
    else:
        b=a[(groupNum//2)::groupNum]
        return midNum(b)

def InsertSort(a,start,end):
    for k in range(start+1,end+1):
        i=k
        while a[i-1]>a[i] and i>start:
            a[i-1],a[i]=a[i],a[i-1]
            i-=1
    return a

def PartionByValue(a,x):
    i=0
    j=0
    for k in range(0,len(a)):
        if a[k]<x:
            a[k],a[i]=a[i],a[k]
            i+=1
    for k in range(i,len(a)):
        if a[k]==x:
            j=k
    a[i],a[j]=a[j],a[i]
    return i

def select(a,i):
    mid=midNum(a)
    k=PartionByValue(a,mid)+1
    if i==k:
        return mid
    else:
        if i<k:
            return select(a[0:k-1],i)
        else:
            return select(a[k::],i-k)

lst=[2,6,3,1,5,0,7,8,4,9]
k=select(lst,10)
print(k)

补充说明: 
等比数列求和问题 
等比数列通项公式:a(m)=a(1)*q^(m-1) 
等比数列求和公式:S(m)=a(1)* ( 1-q^m ) / ( 1-q )

如果a(1)=c*n 
a(m+1)=q*a(m) (q<1) 
可以求的S(m)=c*n* ( 1-q^m ) / ( 1-q )=theta(n)

在此博客中,问题三对应q=0.5,问题四对应q<0.75,所以都是线性时间算法

批注:阶数只是对特别大的数据的时候,阶数越低计算时间越短,数据量小的时候,线性时间的常数比例因子比较影响效果。

时间: 2024-10-12 03:53:07

(转)算法导论—中位数与顺序统计量的相关文章

算法导论 中位数和顺序统计量(python)

第i个顺序统计量:该集合中第i小的元素(建集合排序后第i位 当然算法可以不排序) 中位数:集合中的中点元素 下中位数 上中位数 9.1最大值和最小值 单独的max或min每个都要扫一遍 n-1次比较 如果同时找max和min 要 :1.2个数相互比较 1次{每次选出2个 选n//2次} 2.大的和max比较 3.小的和min比较 找出序列为第i小的数Θ(n) 随机快速排序的运用:(可以回去看快排) 代码: import random def PARTTION(A,p,r): x = A[r] i

算法导论-中位数和顺序统计量

在一个由n个元素组成的集合中,第i个顺序统计量是该集合中第i小的元素.一个中位数是它所属集合的“中点元素”.当n为奇数时,中位数是唯一的,位于i=(n+1)/2处:当n为偶数时,存在两个中位数,分别位于i=n/2和i=n/2+1处.如果不考虑n的奇偶性,中位数总是出现在i=⌊(n+1)/2⌋处(下中位数)和i=⌈(n+2)/2⌉(上中位数). 1.最小值和最大值 在一个有n个元素的集合中,需要做n-1次(上界)比较才能找到最小值或最大值. int MiniValue(const int *A,

算法导论—中位数与顺序统计量

一.选择最大值或者最小值的最优算法 对于长度为n的数组,已证找最大值或者最小值比较操作下界就是n-1.所以只需要让第一个值为初始最大值或者初始最小值,用所有的值与这个值比较,更新这个值即可. def minimum(a): minNum=a[0] for i in range(1,len(a)): if minNum>a[i]: minNum=a[i] return minNum print(minimum ([1,2,3,4,5,6,7,8,9])) 二.同时选择最大值和最小值的快速算法(成对

算法导论-------------中位数和顺序统计学

文章来自网络加课本: 本次学习的内容讨论的问题是在一个由n个不同数值构成的集合中选择第i个顺序统计量问题.主要讲的内容是如何在线性时间内O(n)时间内在集合S中选择第i小的元素,最基本的是选择集合的最大值和最小值.一般情况下选择的元素是随机的,最大值和最小值是特殊情况,书中重点介绍了如何采用分治算法来实现选择第i小的元素,并借助中位数进行优化处理,保证最坏保证运行时间是线性的O(n). 1.基本概念 顺序统计量:在一个由n个元素组成的集合中,第i个顺序统计量是值该集合中第i小的元素.例如最小值是

算法导论第九章中位数和顺序统计量(选择问题)

本章如果要归结成一个问题的话,可以归结为选择问题,比如要从一堆数中选择最大的数,或最小的数,或第几小/大的数等, 这样的问题看似很简单,似乎没有什么可研究的必要,因为我们已经知道了排序算法,运用排序+索引的方式不就轻松搞定了?但细想,排序所带来的时间复杂度是不是让这个问题无形之中变得糟糕.那算法研究不就是要尽可能避免一个问题高复杂度地解决,让那些不敢肯定有无最优解的问题变得不再怀疑,这也是算法研究者所追求的一种极致哲学.既然排序让这个问题解决的性能无法确定,那我们就抛开排序,独立研究问题本身,看

算法导论之七(中位数和顺序统计量之选择算法)

实际生活中,我们经常会遇到这类问题:在一个集合,谁是最大的元素?谁是最小的元素?或者谁是第二小的元素?....等等.那么如何在较短的时间内解决这类问题,就是本文要阐述的. 先来熟悉几个概念: 1.顺序统计量: 在一个由n个元素组成的集合中,第i个顺序统计量(order statistic)是该集合中第i小的元素.最小值是第1个顺序统计量(i=1),最大值是第n个顺序统计量(i=n).   2.中位数: 一个中位数是它所属集合的"中点元素",当n为奇数时,中位数是唯一的,位于i=(n+1

[算法导论 Ch9 中位数和顺序统计量] Selection in O(n)

1. 寻找第k大(小)的数 假设数据存储在数组a[1..n]中 首先,寻找一个数组中最大或者最小的数,因为最大(小)的数一定要比其他所有的数大(小),因此至少要比较完所有的pair才能确定,所以时间复杂度在O(n).那么寻找第k大(小)呢? 比较直观的,就是对数组中国所有的数据先进行排序,在我们这种渣渣的计算机入门选手而言,可选的有QuickSort,MergeSort和HeapSort,甚至是ShellSort等一些比较高级的方法啊...一般的代价都在O(n*logn)上,然后直接取出即可.

第九章 中位数和顺序统计量 9.2 期望为线性时间的选择算法

package chap09_Medians_and_Order_Statistics; import static org.junit.Assert.*; import java.util.Random; import org.junit.Test; public class SearchAlorithms { /** * 分割(快速排序中对数组的分割) * * @param n * @param start * @param end * @return */ protected static

【算法导论学习-016】两个已排过序的等长数组的中位数(median of two sorted arrays)

问题来源 <算法导论>P223 9.3-8: Let X[1..n] and Y[1..n] be two arrays, each containing nnumbers already in sorted order. Give an O(lgn)-time algorithm to find themedian of all 2n elements in arrays X and Y. 翻译过来即:求两个等长(n个元素)的已排序数组A和B的中位数 方案1:对两个数组进行归并直到统计到第n