中位数和顺序统计量---算法导论学习笔记

算法导论断断续续看了一小部分,但是还没有写过总结和笔记,很多思考和学习到的东西都随着时间流失掉了(痛心)。
下面进入正题:
1.最大值和最小值问题
最简单的确定一个有n个元素的集合中最小元素(最大元素)的方法就是所谓“打擂台”的思路。遍历集合,过程中将每个元素与现在所持有的最小元素进行比较,如果该元素小于现有最小元素则更新最小元素为该元素,否则继续遍历。可见至少要进行n-1次比较,从次数看来,这个算法是最优的。
那么,如果要同时找出最小元素和最大元素的话,该怎么做?
(1).若n为奇数,则max=arr[0],min=arr[0];
若n为偶数,则max=arr[0],min=arr[1];
(2).集合中每两个元素组成一对,分别求其大小关系。
(3).遍历集合,将max和min与每对元素集中的最大元素与最小元素比较,进行更新
分奇数和偶数的情况是因为奇数个元素的集合不能被正好分成n/2个集合,所以干脆将第一个元素孤立出来。
现在分析比较次数:
奇数:遍历n/2个子集,max和min分别比较,加上每个子集内部比较,于是总共是3*floor(n/2)次.
偶数:第一次max和min子集的初始化比较,加上(n-2)/2个子集内部比较,加上遍历的2*(n-2)/2次比较,所以总共是3n/2-2次比较。
2.选择算法(期望为线性时间)
这里提供了一个分治算法来确定集合中的第i个元素。

    (1).p为集合第一个元素,r为元素最后一个元素,q为分区关键字索引,i为所求元素在集合中的次序                    
    (2).对集合中的元素进行一次基于快速排序的随机分区(randomized-patition),并得到分区关键元素的索引值q。
    (3).k=q-p+1,得到q之后的分区首元素,此时k代表q在该集合中的索引,而q得到的是整个集合中的索引值.
    (4).若k=i,则返回A「q」,
        若k>i,返回调用select(A,p,q-1,i)
        若k<i,返回调用select(A,q+1,r,i-k)

下面贴上java实现:

import java.util.Random;
public class RandomSelect {
    public static void exchange(int[] arr,int i,int j) {
        if(i<0||i>=arr.length||j<0||j>=arr.length||i==j)
            return;
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

    public static int patition(int[] arr,int p,int r) {
        Random random=new Random();
        int index=Math.abs(random.nextInt(r));
        while(index<p)
            index=Math.abs(random.nextInt(r));
        exchange(arr,r,index);
        int x=arr[r];
        int i=p-1;
        for(int j=p;j<r;j++) {
            if(arr[j]<x) {
                i++;
                exchange(arr,i,j);
            }
        }
        exchange(arr,i+1,r);
        return i+1;
    }

    public static int randomized_select(int[] arr,int p,int r,int i) {
        if(p==r)
            return arr[p];
        int q=patition(arr,p,r);
        int k=q-p+1;
        if(k==i)
            return arr[q];
        if(i<k)
            return randomized_select(arr,p,q-1,i);
        else
            return randomized_select(arr,q+1,r,i-k);
    }
    public static void main(String...args) {
        int[] arr={2,5,4,6,35,11,7,55,3,73,80};
        System.out.println(randomized_select(arr,0,arr.length-1,arr.length));

    }
}

了解了基本的算法,下面对时间期望进行分析:

k-1和n-k分区是随机分区分出的两个子集,对T(n)求期望值
E(T(n))<=E(nk=1·T(max(k1,nk)))+O(n)=1/n·E(T(max(k1,nk)))+O(n)
所以, E[T]<=2/n·k=n/2n1E[T(n)] 接下来将On(n)替换为an,并做一个假设: E[T(n)]<=cn
E[T]<=2/n·k=n/2n1ck+an=cn((cn/4)c/2an) (1) 具体的化简请看《算法导论》p122页的演绎
最终, (cn/4)c/2an>=0 就可以证明(1)式至多为cn,得到结果 n>=2c/(c4a)
如果假设对 n<2c/(c4a) ,只要 T(n)=O(1) 那么 E(T(n))=O(n) ,期望为线性。因此,若集合元素互异,可以做到在线性时间内找到任一顺序统计量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值