Description

给定线性序集中n个元素和一个整数k,n<=2000000,1<=k<=n,要求找出这n个元素中第k小的数。

Input

第一行有两个正整数n,k. 接下来是n个整数(0<=ai<=1e9)。

Output

输出第k小的数

Sample Input

6 3
1 3 5 2 4 6

Sample Output

3

利用快速排序可以找出第k小的,加上随机函数改进一下:

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream> int num[2000001]; void quictSort(int, int, int);
int partition(int, int); int main()
{
int n, m, i;
srand(unsigned(time(NULL))); // 随机函数种子
while (~scanf("%d%d", &n, &m))
{
for (i = 0; i < n; i++)
scanf("%d", &num[i]); quictSort(0, n - 1, m - 1); printf("%d\n", num[m - 1]);
}
return 0;
}
// 快速排序
void quictSort(int left, int right, int mTop)
{
if (left < right)
{
int p = partition(left, right); // 分为两段 if (p == mTop) // 如果随机找到第mTop小就直接返回
return;
if (p < mTop)
quictSort(p + 1, right, mTop); // 找到的位置比mTop小就在[p + 1, right]区间找
if (p > mTop)
quictSort(left, p - 1, mTop); // 找到的位置比mTop大就在[left, p - 1]区间找
}
}
// 从小到大排
int partition(int left, int right)
{
int r = rand() % (right - left + 1) + left; // 随机选择一个数
int key = num[r];
std::swap(num[r], num[left]); // 交换到数组首位
while (left < right)
{// 从数组后面开始, 找比随机选择的数小的, 然后从前找比随机选择的数大的
while (left < right && num[right] >= key)
right--;
if (left < right)
num[left] = num[right]; while (left < right && num[left] <= key)
left++;
if (left < right)
num[right] = num[left];
}
num[left] = key; // 将随机选择的数存回
return left; // 返回随机选择的数分割数组的下标, 左边都是比它小的, 右边都是比它大的
}

中位数法线性时间选择划分:

AC代码:

#include <cstdio>
#include <cstdlib> int num[2000001]; int select(int low, int high, int top);
int partition(int low, int high, int median);
void selectSort(int low, int high);
void swap(int &a, int &b); int main()
{
int n, m, i; while (~scanf("%d%d", &n, &m))
{
for (i = 0; i < n; i++)
scanf("%d", &num[i]); printf("%d\n", select(0, n - 1, m - 1)); /*
for (i = 0; i < n; i++)
printf("%d%c", num[i], i < n - 1 ? ' ' : '\n');
*/
}
return 0;
}
// 中位数法线性时间选择
int select(int low, int high, int top)
{
// 小于75个数据随便用一个排序方法
if (high - low < 74)
{
selectSort(low, high); // 选择排序
return num[low + top]; // 排完序直接返回第low + top的数
} int groupNum = (high - low - 4) / 5; // 每组5个数, 计算多少个组, 从0开始计数 for (int i = 0; i <= groupNum; i++)
{
int start = low + 5 * i; // 每组的起始位置
int end = start + 4; // 每组的结束位置
for (int j = 0; j < 3; j++) // 从小到大冒3个泡
for (int k = start; k < end - j; k++)
if (num[k] > num[k + 1])
swap(num[k], num[k+1]);
swap(num[low + i], num[start + 2]); // 每组的中位数交换到前面第low + i的位置
}
// 上面排完后, 数组low + 0 到 low + groupNum都是每一组的中位数
int median = select(low, low + groupNum, (groupNum + 1) / 2); // 找中位数的中位数
int p = partition(low, high, median); // 将数组分为两段, 左边的小于中位数的中位数, 右边的大于中位数的中位数
int n = p - low; // 计算p到low之间有多少个数, 后面得减掉 if (n == top)
return num[p]; // 如果运气好, 刚好要找的就是中位数
if (n > top)
return select(low, p - 1, top); // n比top大就在左边找
if (n < top)
return select(p + 1, high, top - n - 1); // n比top小就在右边找, 并且top要减去已经大的个数
}
// 以中位数进行分割, 分成两半
int partition(int low, int high, int median)
{
int p;
for (int i = low; i <= high; i++)
if (num[i] == median)
{
p = i;
break;
}
// 将中位数交换到最前面
swap(num[p], num[low]);
// 记下最前面的数
int key = num[low];
// 把小于key的放前面, 大于key的放后面
while (low < high)
{
while (num[high] >= key && low < high)
high--;
if (low < high)
num[low] = num[high];
while (num[low] <= key && low < high)
low++;
if (low < high)
num[high] = num[low];
}
// 分别从两头开始, 找到中间时, 把key存回
num[low] = key;
return low;
}
// 选择排序
void selectSort(int low, int high)
{
for (int i = low; i <= high; i++)
{
int MIN = i;
for (int j = i + 1; j <= high; j++)
if (num[MIN] > num[j])
MIN = j;
swap(num[i], num[MIN]);
}
}
// 交换两个元素
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}

算法:线性时间选择(C/C++)的更多相关文章

  1. [图解算法]线性时间选择Linear Select——<递归与分治策略>

    #include <ctime> #include <iostream> using namespace std; template <class Type> vo ...

  2. 【Unsolved】线性时间选择算法的复杂度证明

    线性时间选择算法中,最坏情况仍然可以保持O(n). 原因是通过对中位数的中位数的寻找,保证每次分组后,任意一组包含元素的数量不会大于某个值. 普通的Partition最坏情况下,每次只能排除一个元素, ...

  3. 算法线性编程珠玑读书笔记之----->使用线性算法求解连续子序列的最大和

    这段时间笔者几篇文章介绍了改算法线性的文章. 关联文章的地址 这个算法我在我的博客里应用动态规划做过,详细实现请参阅我的dp板块,下面给出书上最快的算法,时间复杂度为O(n),称之为线性算法. #in ...

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

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

  5. C++分治策略实现线性时间选择

    问题描述: 给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,即如果将这n个元素依其线性序排列时,排在第k个的元素即为要找到元素. 细节须知:(与之前的随笔相比) (1 ...

  6. 关于曲线 规划 算法 线性 S曲线 贝塞尔曲线

    工控领域经常会涉及速度加减速的算法:线性加减速,S曲线加减速(sin函数,拓展其他三角函数曲线), 贝塞尔曲线,等等. 线性加减速:    设定起始速度V0,目标速度V1,加速时间Ta(s,或加速度) ...

  7. 查找第K小的元素(利用中位数线性时间选择)(C)

    找任意第k个小的元素 #include <stdio.h> #include <stdlib.h> #include <ctime> #include <io ...

  8. 剑指Offer——分治算法

    剑指Offer--分治算法 基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更 ...

  9. K:找寻数组中第n大的数组元素的三个算法

    相关介绍:  给定一个数组,找出该数组中第n大的元素的值.其中,1<=n<=length.例如,给定一个数组A={2,3,6,5,7,9,8,1,4},当n=1时,返回9.解决该问题的算法 ...

随机推荐

  1. spring boot:实现图片文件上传并生成缩略图(spring boot 2.3.1)

    一,为什么要给图片生成缩略图? 1, 用户上传的原始图片如果太大,不能直接展示在网站页面上, 因为不但流费server的流量,而且用户打开时非常费时间, 所以要生成缩略图. 2,服务端管理图片要注意的 ...

  2. Python基础数据类型及其转换

    数据类型: 浮点型float: 3.1415 也就是小数 整型 int: 123,主要用来运算,+-*/ 字符串 str: 'abc?', 记录少量信息 布尔值 bool: True or False ...

  3. 【应用服务 App Service】Azure App Service 中如何安装mcrypt - PHP

    问题描述 Azure App Service (应用服务)如何安装PHP的扩展 mcrypt(mcrypt 是php里面重要的加密支持扩展库) 准备条件 创建App Service, Runtime ...

  4. 面经手册 · 第14篇《volatile 怎么实现的内存可见?没有 volatile 一定不可见吗?》

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.码场心得 你是个能吃苦的人吗? 从前的能吃苦大多指的体力劳动的苦,但现在的能吃苦已经包括太 ...

  5. 更换Centos的yum源

    1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2.下载新的CentOS-Base ...

  6. react-native 签名

    完成项目时,我们需要将项目打包成一个apk,方便测试以及发布版本. 这时,需要把js代码和图片资源都放进apk中, 并且发布版本还需要签名,今天把这一系列操作记录下来. 一.生成离线bundle包 离 ...

  7. Mybatis---01Mybatis动态代理过程分析

    1.通过调试,session调用的getMapper是其实现类DefaultSQLSession中的 //1.读取配置文件 InputStream in = Resources.getResource ...

  8. java数据结构-06双向循环链表

    双向循环链表跟单向链表一样,都是头尾相连,不过单向是尾指向头,双向是头尾互相指,可以从前往后查,也可以从后往前查 无头结点的双向循环链表 public class CircleLinkedList&l ...

  9. 【总结】mybatis分页(实现 + 原理)

    1.mybatis pageHelper分页实现 (1)引入依赖 (2)配置pageHelper插件 <configuration> <!-- 引入 pageHelper插件 --& ...

  10. python数据类型之Number(数字)

    一.Number(数字) 关注公众号"轻松学编程"了解更多. 数据类型 ​ 为什么会有不同的数据类型? ​ 计算机是用来做数学计算的机器,因此它可以处理各种数值,但是计算机能够处理 ...