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. PHP之Trait详解 转

    php从以前到现在一直都是单继承的语言,无法同时从两个基类中继承属性和方法,为了解决这个问题,php出了Trait这个特性 用法:通过在类中使用use 关键字,声明要组合的Trait名称,具体的Tra ...

  2. navicate premium黄色版本破解下载

    百度网盘下载 提取码: tsua 按照电脑安装32位或者64位 安装完成后点击最后一个进行破解汉化

  3. HTML语义化罗嗦罗嗦

    CSS还未诞生之前,为了实现一些样式效果.设计师必须使用一些物理标签,例如font.b等.这样会造成页面中充满了为实现各种样式的标签,特别是使用table标签来实现一些特殊的布局,俗称为"标 ...

  4. 使用OLEDB方式 读取excel和csv文件

    /// <summary> /// 使用OLEDB读取excel和csv文件 /// </summary> /// <param name="path" ...

  5. Excel 导出的方法 之二

    // <summary> /// 导出到Excel lichenghu /// </summary> /// <param name="dt"> ...

  6. APP脱壳方法三

    第一步 手机启动frida服务 第二步 手机打开要脱壳的app 第三步编辑hook代码 agent.js /* * Author: hluwa <hluwa888@gmail.com> * ...

  7. 【应用服务 App Service】NodeJS +Egg 发布到App Service时遇见 [ERR_SYSTEM_ERROR]: A system error occurred:uv_os_get_passwd returned ENOENT(no such file or directory)

    问题情形 本地NodeJS应用使用Egg脚手架构建,本地运行测试完全没有问题,发布后App Service后不能运行.通过登录到kudu后(https://<your web site>. ...

  8. MySQL数据库基础-3-SQL 基本概念

    SQL 基本概念 约束:constraint,表中的数据要遵守的限制 主键:一个或多个字段的组合,填入的数据必须能在本表中唯一标识本行:必须提供数据,即NOT NULL,一个表只能有一个 惟一键:一个 ...

  9. MapReduce工作原理详解

    文章概览: 1.MapReduce简介 2.MapReduce有哪些角色?各自的作用是什么? 3.MapReduce程序执行流程 4.MapReduce工作原理 5.MapReduce中Shuffle ...

  10. json针对list map set 应用

    package JSONtest; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; im ...