分治——线性时间选择算法
文章目录
- 1. 选择问题
- 2. 解决方法
- 3. 代码示例
顾名思义,“线性时间选择”就是“选择问题”的“线性时间”算法。
1. 选择问题
元素选择问题:给定一个能够线性排序的集合(该集合中有 n 个元素)和 一个整数 k(1≤k≤n1 \le k \le n1≤k≤n) ,找出这 n 个元素中第 k 小的元素。
时间下界:
当 k=1或k=nk = 1 或 k = nk=1或k=n时,时间复杂度为 O(n)O(n)O(n)
当 k≤n/log(n)或k≥n−n/log(n)时k \le n/log(n) 或 k \ge n - n/log(n)时k≤n/log(n)或k≥n−n/log(n)时,时间复杂度为O(n+klog(n))=O(n)O(n + klog(n)) = O(n)O(n+klog(n))=O(n)(堆排序)
2. 解决方法
方法一:先排序,再找第 k 小的数。O(nlogn)O(nlogn)O(nlogn)时间
方法二:随机选择算法:使用快速排序方法, 最多对一段继续分解 最坏时间O(n2)O(n^2)O(n2), 平均时间O(n)O(n)O(n)
RamdomizedPartition(a, p, r) 快排中的分解算法
i=Ramdom(p,r) //在p:r中随机选择一个数i
交换 a[i] 与 a[p] //将a[i]换到左端点
执行Partition(a,p,r)
RamdomizedPartition(a, p, r) //排序a[p:r] { i = Ramdom(p, r); swap(a[i], a[p]);return Partition(a, p, r); }
RandomSelect(a, p, r)
RSelect(a,p,r,k) //选择a[p:r]中第k小数 { if (p == r)return a[p];mid=RamdomizePartition(a, p, r); if( mid >= k)return (RSelect(a, p, mid, k)); else return (RSelect(a, mid + 1, r, k - mid); } //初略时间分析: T(n) = T(9n/10) + O(n) = O(n)
方法三:线性时间选择算法 Select() :对快速排序的改进,最坏时间O(n)O(n)O(n)。
- 将 n 个元素,分成⌈n/5⌉\lceil n/5 \rceil⌈n/5⌉组,取出每组的中位数(第三小的元素)
- 取出⌈n/5⌉\lceil n/5 \rceil⌈n/5⌉个中位数的中位数(Select函数可以取中位数)
- 利用快排中的分解函数 Partition(),以所求中位数为基准,划分 a[p : r] 为两段。
- 取其中一段进行递归。
template <typename Type>
Type Select(Type a[], int p, int r, int k)
{ if( r - p < 75 ) { 直接对数组a[p:r]排序; return a[p+k-1];}for( int i = 0; i <= (r - p - 4) / 5 ; i++ ) //分 n/5 组, 取各组中位数{swap(a[p + 5*i]至a[p+5*i+4]的第3小元素, a[p+i]);}Type x = Select(a, p, p+(r-p-4)/5, (r-p-4)/10); //取中位数的中位数, T(n/5)int i = Partition(a, p, r, x), j = i - p + 1; if ( k == j ) return a[i];else if ( k < j ) return Select(a,p,i-1,k); //选择左片递归, 最多T(3n/4)else return Select(a,i+1,r,k-j); //选择右片递归, 最多T(3n/4)}
时间复杂度分析:
总结:算法优化的历程
算法 | 快排 | 随机选择 | 线性时间选择 |
---|---|---|---|
时间复杂度 | O(nlog(n))O(nlog(n))O(nlog(n)) | O(n)−−O(n2)O(n) -- O(n^2)O(n)−−O(n2) | O(n)O(n)O(n) |
基准值 | a[p] | random | 中位数 |
3. 代码示例
附:line-time-select.c
#include <stdio.h>
#define MAX 100000
int num[MAX];
// 选择排序
void slsort(int p, int q)
{for (int i = p + 1; i <= q; i++){int temp = num[i], j = i - 1;while (j >= p){if (num[j] > temp){num[j + 1] = num[j];j--;}elsebreak;}num[j + 1] = temp;}
}
// 分解函数
int Partition(int p, int q, int mid)
{int i = p, j = q;while (i <= q && j >= p){while (num[i] < mid){i++;}while (num[j] > mid){j--;}if (i >= j)break;else{int temp = num[i];num[i] = num[j];num[j] = temp;i++, j--;}}return j;
}
// 选择函数
int Select(int p, int q, int k)
{if (q - p < 75){slsort(p, q);return num[p + k - 1];}// 选出 n/5 组中每个组的中位数for (int i = 0; i <= (q - p - 4) / 5; i++){slsort(p + 5 * i, p + 5 * i + 4);int temp = num[p + 5 * i + 2];num[p + 5 * i + 2] = num[p + i];num[p + i] = temp;}// 选出各种中位数的中位数 midint mid = Select(p, p + (q - p - 4) / 5, ((q - p - 4) / 5 + 1) / 2);// 以 mid 为基准进行分解int mid_id = Partition(p, q, mid);int mid_rank = mid_id - p + 1;// 递归条件判断if (k == mid_rank){return num[mid_id];}else if (k < mid_rank){return Select(p, mid_id, k);}else{return Select(mid_id + 1, q, k - mid_rank);}
}
int main(int argc, char const *argv[])
{int i = 0, k;while (scanf("%d", &num[i]) != EOF) {i++;}scanf("%d", &k); // 选择第几小的元素if( k > i)printf("error!\n");elseprint("%d\n", Select(0, i, k));return 0;
}
分治——线性时间选择算法相关推荐
- 线性时间选择算法的分治思想:邮局选址问题和士兵战队问题
一. 实验题目 1. 邮局选址问题 在一个按照东西和南北方向划分成规整街区的城市里,n 个居民点散乱地分 布在不同的街区中.用 x 坐标表示东西向,用 y 坐标表示南北向.各居民点的 位置可以由坐标( ...
- Top k问题(线性时间选择算法)
问题描述:给定n个整数,求其中第k小的数. 分析:显然,对所有的数据进行排序,即很容易找到第k小的数.但是排序的时间复杂度较高,很难达到线性时间,哈希排序可以实现,但是需要另外的辅助空间. 这里我提供 ...
- 线性时间选择【递归分治法】
顾名思义:这篇文章讲解的就是如果用线性时间算法来作出元素选择问题. 问题描述:给定线性序集中n个元素和一个整数k,1<=k<=n.要求找出这n个元素中第k小的元素,即如果将这个n个元素依其 ...
- 算法设计与分析——递归与分治策略——线性时间选择
顾名思义:这篇文章讲解的就是如果用线性时间算法来作出元素选择问题. 问题描述:给定线性序集中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: ...
- 线性时间选择求第k小数(分治)
目录 线性时间选择 优化 对划分进行随机数改良 取中位数进行划分 全部代码 线性时间选择 问题描述:给定线性序集中 n 个元素和一个整数 k(1 <= k <= n),要求找出着 n 个元 ...
- 【分治】线性时间选择(C++)
一.线性时间选择 1. 问题描述 给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素. 2. 线性时间选择-随机划分 算法步骤: 生成1个随机数 i ,将数组a[p:r] ...
- 算法笔记——【分治法】线性时间选择
线性时间选择问题:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,(这里给定的线性集是无序的). 随机划分线性选择 线性时间选择随机划分法可以模仿随机化快速排序算法设 ...
- 递归与分治java策略实验报告_递归与分治策略–计算机算法设计与分析
递归概念:直接或者间接调用自身的算法,称为递归运算. 分治思想:把一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相等,递归解决子问题后再将结果合并 下方为一些应用函数.因为 ...
- 分治法:线性时间选择
大家好,我是连人,本期分享线性时间选择问题. 线性时间选择是基于快速排序的一种延申,本质上和快排具有类似的地方.它的目的是找出这个数组中第k小的值. 既然只需找出1个值,我们就不必将整个数组排序.通过 ...
最新文章
- 面试:说说你对“零拷贝”的理解?
- 【招聘(深圳)】轻岁 诚聘.NET Core开发
- 在modelarts上部署backend为TensorFlow的keras模型
- 用vim替代source insight
- 多线程 Threading Multiprocessing(Python)
- Redis操作工具类——RedisUtil
- StackPanel
- Win10显示无网络(无Internet连接)但能上网的解决办法
- EAccessViolation型错误
- 挑战微软 + GitHub!谷歌联手 Replit,升级 AI 编程“神器”:曾拒绝微软 10 亿美元的收购...
- openwrt pptpd start 报错validation filed
- 沙特国王科技大学计算机专业,沙特国王科技大学好不好?在世界的排名怎么样啊?哪个专业最强?...
- java正则校验密码 长度不少于8位且至少包含大写字母、小写字母、数字和特殊符号中的四种组合 或者 其中任意三种组合
- Chapter 14
- [转] http、https 等 常用默认端口号
- VB.net 删除文件、文件夹
- 电脑接显示屏后提示计算机休眠,解决方法:主机正常。电脑显示器(hp)睡眠状态...
- 易语言 上传文件到远程服务器,易语言与向远程服务器发送文件夹
- Android使用GridView实现俄罗斯方块(附源码)(三)
- 难怪好人有恶报,原来秘密在这里
热门文章
- 算法设计与分析基础知识总结——dayOne
- 信息系统项目管理师-学习笔记与复习资料
- Maven的安装与配置教程
- python中win32api模块_解决在Python中使用Win32api报错的问题,No module named win32api
- 字节跳动开源!超好用的视频抠图工具;GitHub开源项目维护协作指南;自动化数据清洗工具包;强化学习入门教程;前沿论文 | ShowMeAI资讯日报
- TP-LINK WR703N 变砖救活
- idea java EclipseFormatter代码格式化模板
- 台式计算机如何连接网络,台式机如何去连接网络
- 用java开发pc软件
- 适合计算机类研究生参加的比赛