线性时间选择算法(Java)
线性时间选择算法(Java)
- 线性时间选择算法
- 随机划分线性选择
- 分析
- 代码
- 利用中位数线性时间选择
- 分析
- 例题
- 代码
线性时间选择算法
最近算法课的知识点之一,自己以前没遇见过(是我菜了没错),这次写一篇。
那么什么是线性时间选择呢???一句话,在线性时间内完成选择。
一般情况下是这样的,我们想要找出一个数组中的最大值或最小值,那就只需要一次排列,然后输出第一个或最后一个元素就行了,但如果是要找出一个数组中的第k小的元素呢?
在某些特殊情况下,很容易设计出解选择问题的线性时间算法。如:当要选择最大元素或最小元素时,显然可以在O(n)时间完成。(遍历一次)
一般的选择问题,特别是中位数的选择问题似乎比最小(大)元素要难。但实际上,从渐近阶的意义上,它们是一样的。也可以在O(n)时间完成。
之前我记得我更过一篇,里面说到就是先排个序,然后通过下标去得到,因此这个问题的解决效率取决于排序算法的效率。
但是现在不一样了,我们有了更好的办法。
随机划分线性选择
分析
随机划分线性选择。模仿快速排序算法,对数组在left——right范围内进行一次划分(partition方法,我们这里默认采用随机元素为基准),得到基准下标i,不大于基准的在左边,比基准大的在右边。计算出left——i(包含i)中有多少个元素(j),与k进行比较。
- 如果k<j,说明当前left——right中第k小的在左边序列中,那么从left——i-1继续上述步骤寻找第k小。
- 如果k=j,说明基准i就是left——right中第k小,返回a[j]。(因为前面的都不大于它,后面的都大于它,不管左边是序列怎么排的,整体第k(j)小就是他)
- 如果k>j,说明第k小在右边序列,大于基准a[i],那么从i+1——right继续划分,并将k改为k-j。(整体序列提出了前j个元素,那么第k小在剩下的序列中就是第k-j小了)
一直到left=right的时候就可以返回a[left]了(其实我觉得如果有上述2的情况的话就不需要这个了)
这是课堂上PPT给的思路
这是算法导论的(就是我刚刚说的)
代码
/** @Title randomizedSelect* @Description 基于随机元素为基准的线性时间选择* @author 滑技工厂* @Date 2020/3/26* @param [a, L, R, k -> L---R中的第k小]* @return int* @throws*/public static int randomizedSelect(int[] a, int L, int R, int k) {if (L == R)return a[L];//获取为基准的随机元素的下标int i = randomizedPartition(a, L, R);//j为划分后左序列到基准(包含基准)的元素个数int j = i - L + 1;if (k < j)//如果k小于j,说明在基准i的左边return randomizedSelect(a, L, i - 1, k);else if (k == j)//return a[i];else//k大于j 说明在i的右边序列return randomizedSelect(a, i + 1, R, k - j);}
利用中位数线性时间选择
分析
算法的思路:如果能在线性时间内找到一个划分基准使得按这个基准所划分出的2个子数组的长度都至少为原数组长度的ε倍(0<ε<1),那么就可以在最坏情况下用O(n)时间完成选择任务。例如,当ε=9/10,算法递归调用所产生的子数组的长度至少缩短1/10。所以,在最坏情况下,算法所需的计算时间T(n)满足递推式T(n)<=T(9n/10)+O(n)。由此可得T(n)=O(n)。
先描述下过程。
将n个输入元素划分成n/5个组,每组5个元素,最只可能有一个组不是5个元素。用任意一种排序算法,将每组中元素排好序,并取出中位数,共n/5个。
递归调用Select来找出这n/5个元素中的中位数。如果n/5是个偶数,就找它两个中位数中较大的一个。以该元素作为划分基准。
这种情况下,找出的基准x至少比3(n-5)/10个元素大,同理也比3(n-5)/10个元素小。(下图中箭头指向是从大到小,红+蓝的数量为3(n-5)/10)而当n>=75时,3(n-5)/10>=n/4所以按此基准划分所得的两个子数组的长度都至少缩短1/4。
得到划分基准后,后面就和第一个一样,计算左序列个数,和k进行比较。判断在左序列还是右序列,在递归调用该方法(k在右序列仍要减j),直到k=j为止,返回那个基准。
例题
代码
/** @Title select* @Description 利用中位数线性时间选择* @author 滑技工厂* @Date 2020/3/27* @param [a, l, r, k]* @return int* @throws*/public static int select(int[] a, int l, int r, int k) {if (r - l < 75) {insertSort(a, l, r); //用插入排序进行排序return a[l + k - 1];}int group = (r - l + 5) / 5;for (int i = 0; i < group; i++) {int left = l + 5 * i;int right = (l + i * 5 + 4) > r ? r : l + i * 5 + 4; //如果超出右边界就用右边界赋值int mid = (left + right) / 2;insertSort(a, left, right);swap(a, l + i, mid); // 将各组中位数与前i个}int pivot = select(a, l, l + group - 1, (group + 1) / 2); //找出中位数的中位数int p = partition(a, l, r, pivot); //用中位数的中位数作为基准的位置int j = p - l + 1; //leftNum用来记录基准位置的前边的元素个数if (k == j)return a[p];else if (k < j)return select(a, l, p - 1, k);else //若k在基准位子的后边,则要从基准位置的后边数起,即第(k - leftNum - 1)个return select(a, p + 1, r, k - j - 1);}
详细代码去我的G站
作业又完成了一个 (^-^)V
线性时间选择算法(Java)相关推荐
- Top k问题(线性时间选择算法)
问题描述:给定n个整数,求其中第k小的数. 分析:显然,对所有的数据进行排序,即很容易找到第k小的数.但是排序的时间复杂度较高,很难达到线性时间,哈希排序可以实现,但是需要另外的辅助空间. 这里我提供 ...
- 线性时间选择算法的分治思想:邮局选址问题和士兵战队问题
一. 实验题目 1. 邮局选址问题 在一个按照东西和南北方向划分成规整街区的城市里,n 个居民点散乱地分 布在不同的街区中.用 x 坐标表示东西向,用 y 坐标表示南北向.各居民点的 位置可以由坐标( ...
- 线性时间选择【递归分治法】
顾名思义:这篇文章讲解的就是如果用线性时间算法来作出元素选择问题. 问题描述:给定线性序集中n个元素和一个整数k,1<=k<=n.要求找出这n个元素中第k小的元素,即如果将这个n个元素依其 ...
- 算法笔记——【分治法】线性时间选择
线性时间选择问题:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,(这里给定的线性集是无序的). 随机划分线性选择 线性时间选择随机划分法可以模仿随机化快速排序算法设 ...
- 算法设计与分析——递归与分治策略——线性时间选择
顾名思义:这篇文章讲解的就是如果用线性时间算法来作出元素选择问题. 问题描述:给定线性序集中n个元素和一个整数k,1<=k<=n.要求找出这n个元素中第k小的元素,即如果将这个n个元素依其 ...
- 线性时间选择-分治算法
问题描述 给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素.在线性时间内O(n)? k=1; 最小元素 O(n) k=n; 最大元素 O(n) k=(n+1)/2: ...
- 数据结构和算法(Java)-张晨光-专题视频课程
数据结构和算法(Java)-579人已学习 课程介绍 如果说各种编程语言是程序员的招式,那么数据结构和算法就相当于程序员的内功. 想写出精炼.优秀的代码,不通过不断的锤炼,是很难做到的 ...
- 线性查找法java代码_Java线性查找和二分查找
Java线性查找和二分查找. 一 线性查找 定义:在一列给定的值中进行搜索,从一端开始逐一检查每个元素,直到找到所需元素的过程. 线性查找又称为顺序查找.如果查找池是某种类型的一个表,比如一个数组,简 ...
- 数据结构与算法-java笔记一 更新中
数据结构与算法-java笔记一 更新中 数据结构与算法 什么是数据结构.算法 数据结构学了有什么用: 线性结构 数组 特点 应用 链表 存储结构 链表类型 单链表 双向链表 双向循环链表 链表与数组的 ...
- 排序算法python实现_合并排序算法– Java,C和Python实现
排序算法python实现 Merge sort is one of the most efficient sorting algorithms. It works on the principle o ...
最新文章
- 【Linux 内核】进程管理 ( 进程相关系统调用源码分析 | fork() 源码 | vfork() 源码 | clone() 源码 | _do_fork() 源码 | do_fork() 源码 )
- final关键字的几大特征
- Windows下MetaMap工具安装
- Spring Boot和Swagger UI
- mysql文件_mysql 的各种文件详细说明
- AndroidStudio安卓原生开发_UI控件_Spinner用法_下拉选择框---Android原生开发工作笔记100
- python画roc曲线需要什么数据,Python ROC曲线绘制
- Alluxio部署(local模式)
- iOS开发之原生二维码扫描rectOfInterest扫描区域
- Quartus II 与ModelSim-Altera联合仿真PLL
- ZigBee 协议栈的调度顺序代码分析
- python 官方中文文档(在线)
- 【高性能计算背景】《并行计算教程简介》翻译 - 中文 - 1 / 4
- element-ui表格的滚动条样式修改(当固定table表格高度时默认滚动条样式太丑)
- 不会做动画的程序猿不是好的动画师(如何用css3动画做动画)
- 用Excel表格拆分一行里的内容
- 【Mac】快捷键锁屏
- usb gaghet hid 模拟鼠标键盘的绝对值描述
- 区别:KL散度,JS散度,Wasserstein距离(EMD)
- 初学以太坊--环境搭建篇