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. 第六章 IP基本原理

    一.引入 1.IP是网络层协议,也是当今应用最广泛的网络协议之一 2.IP协议规定了数据的封装方式,网络节点的标识方法,用于网络上数据的端到端的传递. 二.IP协议概述 1.IP及相关协议 2.IP的 ...

  2. 读书摘要观后感与总结:《Glibc内存管理:ptmalloc2源代码分析》

    更新中 在Linux平台下做漏洞利用的时候,针对于Heap部分总是有些不求甚解,下面开个博文来记录下<Glibc内存管理:ptmalloc2源代码分析>这本书的读后感和收获,一些简单的点将 ...

  3. C语言,产生一组数字,并将其写入txt文档中

    #include<stdio.h> /*产生一组连续的数字,并将其写到txt文档中*/ /*说明:本程序在在win10 系统64位下用Dev-C++ 5.11版本编译器编译的*/int m ...

  4. Navicat连接远程MySQL8.0数据库

    前言: 如果你有一台服务器,并且安装了Mysql8.0及以上版本数据库.此时想通过本地Navicat软件连接远程服务器上的mysql数据库.那么接下来你就要完成以下准备工作: 登录远程服务器上的数据库 ...

  5. makefile管理项目

    makefile: 管理项目. 命名:makefile Makefile --- make 命令 1 个规则: 目标:依赖条件 (一个tab缩进)命令 1. 目标的时间必须晚于依赖条件的时间,否则,更 ...

  6. 部署SpringBoot项目jar包到云服务器

    前言 做安卓开发也有三四年了,但是对网络这块什么http.tcp/ip之类的一直不理解.并且想自己做一些小项目练练手的时候,数据库直接存在apk里总不是滋味,所以这次站在安卓开发的角度尝试着做一做简单 ...

  7. 【总结】mysql调优

    一.事务 1.事务的特性 (1)原子性(Atomicity),可以理解为一个事务内的所有操作要么都执行,要么都不执行. (2)一致性(Consistency),可以理解为数据是满足完整性约束的,也就是 ...

  8. LOJ 6068「2017 山东一轮集训 Day4」棋盘

    题意 一个 \(n\times n\) 的棋盘上面有若干障碍物. 定义两个棋子可以互相攻击当且仅当这两个棋子的横坐标或纵坐标相等而且中间不能隔着障碍物.(可以隔棋子) 有 \(q\) 次询问,每次询问 ...

  9. BCVP,想真正为社区做努力的开发者们

    基于Net/Core,快速搭建 API & SPA 及微服务应用组织 BASE NETCORE (VUE) PROJECT TEAM 每一个.NET开发者都可以通过自己的开源项目(最好可以配套 ...

  10. 面试时说Redis是单线程的,被喷惨了!

    Redis是单线程的,这话搁以前,是横着走的,谁都知道的真理.现在不一样,Redis 变了.再说这句话,多少得有质疑的语气来跟你辩驳一番.意志不坚定的,可能就缴械投降,顺着别人走了. 到底是什么样的, ...