文章目录

  • 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)

  1. RamdomizedPartition(a, p, r) 快排中的分解算法

    1. i=Ramdom(p,r) //在p:r中随机选择一个数i

    2. 交换 a[i] 与 a[p] //将a[i]换到左端点

    3. 执行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);
    }
    
  2. 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)。

  1. 将 n 个元素,分成⌈n/5⌉\lceil n/5 \rceil⌈n/5⌉组,取出每组的中位数(第三小的元素)
  2. 取出⌈n/5⌉\lceil n/5 \rceil⌈n/5⌉个中位数的中位数(Select函数可以取中位数)
  3. 利用快排中的分解函数 Partition(),以所求中位数为基准,划分 a[p : r] 为两段。
  4. 取其中一段进行递归。
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. 线性时间选择算法的分治思想:邮局选址问题和士兵战队问题

    一. 实验题目 1. 邮局选址问题 在一个按照东西和南北方向划分成规整街区的城市里,n 个居民点散乱地分 布在不同的街区中.用 x 坐标表示东西向,用 y 坐标表示南北向.各居民点的 位置可以由坐标( ...

  2. Top k问题(线性时间选择算法)

    问题描述:给定n个整数,求其中第k小的数. 分析:显然,对所有的数据进行排序,即很容易找到第k小的数.但是排序的时间复杂度较高,很难达到线性时间,哈希排序可以实现,但是需要另外的辅助空间. 这里我提供 ...

  3. 线性时间选择【递归分治法】

    顾名思义:这篇文章讲解的就是如果用线性时间算法来作出元素选择问题. 问题描述:给定线性序集中n个元素和一个整数k,1<=k<=n.要求找出这n个元素中第k小的元素,即如果将这个n个元素依其 ...

  4. 算法设计与分析——递归与分治策略——线性时间选择

    顾名思义:这篇文章讲解的就是如果用线性时间算法来作出元素选择问题. 问题描述:给定线性序集中n个元素和一个整数k,1<=k<=n.要求找出这n个元素中第k小的元素,即如果将这个n个元素依其 ...

  5. 线性时间选择-分治算法

    问题描述  给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素.在线性时间内O(n)? k=1; 最小元素 O(n) k=n; 最大元素 O(n) k=(n+1)/2: ...

  6. 线性时间选择求第k小数(分治)

    目录 线性时间选择 优化 对划分进行随机数改良 取中位数进行划分 全部代码 线性时间选择 问题描述:给定线性序集中 n 个元素和一个整数 k(1 <= k <= n),要求找出着 n 个元 ...

  7. 【分治】线性时间选择(C++)

    一.线性时间选择 1. 问题描述 给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素. 2. 线性时间选择-随机划分 算法步骤: 生成1个随机数 i ,将数组a[p:r] ...

  8. 算法笔记——【分治法】线性时间选择

    线性时间选择问题:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,(这里给定的线性集是无序的). 随机划分线性选择 线性时间选择随机划分法可以模仿随机化快速排序算法设 ...

  9. 递归与分治java策略实验报告_递归与分治策略–计算机算法设计与分析

    递归概念:直接或者间接调用自身的算法,称为递归运算. 分治思想:把一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相等,递归解决子问题后再将结果合并 下方为一些应用函数.因为 ...

  10. 分治法:线性时间选择

    大家好,我是连人,本期分享线性时间选择问题. 线性时间选择是基于快速排序的一种延申,本质上和快排具有类似的地方.它的目的是找出这个数组中第k小的值. 既然只需找出1个值,我们就不必将整个数组排序.通过 ...

最新文章

  1. 面试:说说你对“零拷贝”的理解?
  2. 【招聘(深圳)】轻岁 诚聘.NET Core开发
  3. 在modelarts上部署backend为TensorFlow的keras模型
  4. 用vim替代source insight
  5. 多线程 Threading Multiprocessing(Python)
  6. Redis操作工具类——RedisUtil
  7. StackPanel
  8. Win10显示无网络(无Internet连接)但能上网的解决办法
  9. EAccessViolation型错误
  10. 挑战微软 + GitHub!谷歌联手 Replit,升级 AI 编程“神器”:曾拒绝微软 10 亿美元的收购...
  11. openwrt pptpd start 报错validation filed
  12. 沙特国王科技大学计算机专业,沙特国王科技大学好不好?在世界的排名怎么样啊?哪个专业最强?...
  13. java正则校验密码 长度不少于8位且至少包含大写字母、小写字母、数字和特殊符号中的四种组合 或者 其中任意三种组合
  14. Chapter 14
  15. [转] http、https 等 常用默认端口号
  16. VB.net 删除文件、文件夹
  17. 电脑接显示屏后提示计算机休眠,解决方法:主机正常。电脑显示器(hp)睡眠状态...
  18. 易语言 上传文件到远程服务器,易语言与向远程服务器发送文件夹
  19. Android使用GridView实现俄罗斯方块(附源码)(三)
  20. 难怪好人有恶报,原来秘密在这里

热门文章

  1. 算法设计与分析基础知识总结——dayOne
  2. 信息系统项目管理师-学习笔记与复习资料
  3. Maven的安装与配置教程
  4. python中win32api模块_解决在Python中使用Win32api报错的问题,No module named win32api
  5. 字节跳动开源!超好用的视频抠图工具;GitHub开源项目维护协作指南;自动化数据清洗工具包;强化学习入门教程;前沿论文 | ShowMeAI资讯日报
  6. TP-LINK WR703N 变砖救活
  7. idea java EclipseFormatter代码格式化模板
  8. 台式计算机如何连接网络,台式机如何去连接网络
  9. 用java开发pc软件
  10. 适合计算机类研究生参加的比赛