一.什么是中位数?

在一个n个元素顺序排列的集合中,一个中位数是它所属集合的中点元素

用公式表达中位数的位置就是:

1.当n为奇数时:
i=(n+1)/2;

2.当n为偶数时,有两个中位数:
i=n/2 ;
i=n/2+1;

因此,若不考虑n的奇偶性,中位数总是出现在 :i=(n+1)/2处和i=(n+2)/2处。

为了方便起见,以后博客的内容默认中位数在:(n+1)/2处

二.本章主要内容:

本章将讨论从一个有由n个互不相同的元素组成的集合中选择第i个顺序统计量(就是在顺序的排序的下第i个元素)的问题。
于是我们可以对输入和输出有如下的定义:

输入:一个包含n个数的集合A和一个整数i,1<=i<=n。
输出:元素x,且在A中恰好有i-1个小于它的元素。

我们很容易的知道可以通过排序算法将数组A排个序,然后找出第i个元素就可以解决这个问题。但是有没有更快的算法呢?

当然有,这个就是本章的内容。

三.具体策略:

1.特例:最小值和最大值
我们要知道:如果我们为了确定n个元素中的最小值或最大值,必须要做n-1次比较。

那么如果我们要同时确定最大值和最小值,就一定要进行2n-2次比较吗?

事实上,我们有只需要3n/2次比较就可以同时找到最大值和最小值的方法!!

做法如下:
(1)首先,我们将一对输入元素相互进行比较
(2)然后把较小的与当前最小值比较,把最大的与当前最大值进行比较。
这样,对每两个元素共需三次比较。

那么如何设定当前的最小值和最大值呢?
这个取决于n是奇数还是偶数:如果n是奇数,最大值最小值都是第一个元素。
如果n是偶数,就对前两个元素做一次比较来决定最大值最小值。

算法java代码实现:

public class MinAMax {int max;int min;public void MaxMin(int a[]){if(a.length%2==1){//如果数组a中元素有奇数个max=min=a[0];//将第一个元素默认为最大值和最小值for(int i=1;i<a.length;i+=2) {//从第二个元素开始成对向后循环,直到结束if(a[i]>a[i+1])//比较两个元素,如果前者大于后者,互换Swap(a,i,i+1);if(a[i]<min)//将较小者与当前最小值比较min=a[i];if(a[i+1]>max)//将较大者与当前最大值比较max=a[i+1];}} else{//否则数组a中元素有偶数数个//将前两个元素的值赋给最大和最小值if(a[0]>a[1]) {max=a[0];min=a[1];} else{max=a[1];min=a[0];}for(int i=2;i<a.length;i+=2){//从第三个元素开始成对向后循环,直到结束if(a[i]>a[i+1])Swap(a,i,i+1);if(a[i]<min)min=a[i];if(a[i+1]>max)max=a[i+1];}}}//交换函数,事项数组中两个i,j位置元素互换void Swap(int a[],int j,int i){int m;m=a[i];a[i]=a[j];a[j]=m;}public static void main(String[] args) {int a[]={3,2,65,6,8,6};MinAMax text=new MinAMax();text.MaxMin(a);System.out.println("最大值为:"+text.max);System.out.println("最小值为:"+text.min);}
}

结果:

2.一般情况:
主要是分治思想
用到了快排的随机key值的分区方法:

这个方法的时间复杂度仅为O(n);
方法代码:

 /*查找第i大元素方法参数:a:输入数组  p:开始位置  r:结束位置基本思想:用到分治思想*//*** 此方法返回数组中第i小的元素* @param a 输入数组* @param start 开始索引* @param end 结束索引* @param i 规定输出第i小元素* @return*/public int RandonMized_select(int[] a, int start, int end, int i) {if (start == end)return a[start];int keyIndex=Randomized_partition(a, start, end);//        for (int n:a){//            System.out.print(n+" ");
//        }int k=keyIndex-start+1;//System.out.println("["+a[k]+"]");if(i==k){return a[keyIndex];}else if(i<k){return RandonMized_select(a, start,keyIndex-1,i);}else {return RandonMized_select(a, keyIndex + 1, end, i - k);}}//快排一次过程int partition(int[] a, int start, int end) {int key=a[end];int i=start-1;for(int j = start; j<end;j++) {if(a[j]<=key) {i=i+1;Swap(a,i,j);}}Swap(a,i+1, end);return i+1;}//随机产生key值进行一次快排分区int Randomized_partition(int[] a, int start, int end){int i = (int)(Math.random() * (end));if(i<start){i=start;}Swap(a,end,i);return partition(a,start,end);}

测试代码:

public class MinAMax {int max;int min;public static void main(String[] args) {int a[]={3,2,65,6,8,9,7};MinAMax text=new MinAMax();int target=text.RandonMized_select(a,0,a.length-1,4);//在一个数组的0到a.length位置区域中找第4大的元素 System.out.println(target);

结果如下:

《算法导论》第九章.中位数和顺序统计量相关推荐

  1. 算法导论第九章习题9.2-3

    使用迭代版本的随机选择函数实现选择第i小元素.原理与9.2例题相同,该代码为9.2例题的迭代版实现.具体代码如下: #include<iostream> using namespace s ...

  2. 算法导论 第二部分——排序和顺序统计量

    一.堆排序 : 原址排序 复杂度: nlg n 最大堆: A[parent(i)] > = A[i] 最小堆: A[parent(i)] < = A[i] 除了最底层外,其它层都是满状态. ...

  3. 【Java数据结构与算法】第九章 顺序查找、二分查找、插值查找和斐波那契查找

    第九章 顺序查找.二分查找.插值查找和斐波那契查找 文章目录 第九章 顺序查找.二分查找.插值查找和斐波那契查找 一.顺序查找 1.基本介绍 2.代码实现 二.二分查找 1.基本介绍 2.代码实现 三 ...

  4. 我眼中的算法导论 | 第一章——算法在计算中的作用、第二章——算法基础

    一个小白的算法学习之路.读<算法导论>第一天.本文仅作为学习的心得记录. 算法(Algorithm) 对于一个程序员来说,无论资历深浅,对算法一词的含义一定会或多或少有自己的体会,在< ...

  5. 操作系统导论 第九章 调度:比例份额

    文章目录 第九章 调度:比例份额 9.1 基本概念:彩票数代表份额 9.2 彩票机制 9.3 实现 9.4 步长调度 9.5 小结 第九章 调度:比例份额 在本章,我们将看到一个不同类型的调度程序–比 ...

  6. 【算法导论】学习笔记——第9章 中位数和顺序统计量

    在一个由n个元素组成的集合中,第i个顺序统计量(order statistic)是该集合中第i小的元素.用非形式化的描述来说,一个中位数(median)使它所属集合的"中点元素". ...

  7. 算法导论2-9章补充几道题

    本篇博文意在对前几章中遗漏的,本人觉得有意思的习题当独拿出来练练手. 1.习题2-4,求逆序对,时间复杂度要求Θ(nlgn) 定义:对于一个有n个不同的数组A, 当i<j时,存在A[i]> ...

  8. 计算机系统导论第九章,计算机系统导论 -- 读书笔记 -- 第三章 程序的机器级表示 (持续更新)...

    计算机系统导论 -- 读书笔记 -- 第三章 程序的机器级表示 (持续更新) 第三章 程序的机器级表示 3.1 历史观点 3.2 程序编码 1. 命令行 (1)编译 Linux> gcc -Og ...

  9. 算法 【第九章】动态规划问题

    动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推的方式去解决. 动态规划的核心点:定义状态与转移方程(最优子结构) 重新定义问题: 一.最长上升子序列(LIS):给定一个序 ...

最新文章

  1. R语言merge函数全连接dataframe数据(Full (outer) join)、merge函数进行全连接必须将参数all设置为true(all=TRUE)、默认merge函数通过公共列名合并数
  2. java word表格_Java 添加Word表格行或列
  3. JAVA Thread Dumps 三部曲
  4. Python 技术篇-使用opencv库读取中文路径图片报错解决办法
  5. Maven父子工程配置文件详解
  6. C#教程8:面向对象编程【01】
  7. 55岁加入Google做程序员,69岁还在编程,这才是代码人生
  8. 机器学习导论(张志华):多项式分布
  9. OpenCASCADE:Modeling Algorithms模块几何工具之插值
  10. 20162318 2018-2019-2《网络对抗技术》Exp1 PC平台逆向破解
  11. 利用单臂路由实验VLAN间路由
  12. NET Core微服务之路:基于Ocelot的API网关Relay实现--RPC篇
  13. C Runtime Library来历, API, MFC, ATL关系
  14. 初识ADT--抽象数据类型
  15. 干货!国外关于高速PCB设计的技术书籍和资料介绍
  16. python爬楼梯问题_python解决上楼梯问题
  17. 差分隐私——高斯机制(The Gaussian Mechanism)
  18. 2015年3月苹果新的审核标准(中文)
  19. autojs实用文档
  20. html左侧导航栏点击下拉菜单,HTML+CSS实现下拉菜单

热门文章

  1. 使用a标签时不用href=““调转页面
  2. ansible命令应用
  3. 如何在Windows 10上使用Microsoft Defender防病毒进行扫描
  4. Python数据分析师薪资大赏(内附学习资料)
  5. 总体样本与样本均值X拔的一个重要公式推导
  6. .NET 控件集 ComponentOne 2018V2正式发布,提供轻量级的 .NET BI 仪表板
  7. 转载 感受K2.Net 2003工作流解决方案
  8. 数字趣解-不可思议的《魔兽世界》
  9. Javascript日期的Format与Parse
  10. [wayfarer]PetShop之表示层设计