Acwing.786 第k个数(图解快速选择算法)

简介: Acwing.786 第k个数(图解快速选择算法)

题目:

给定一个长度为 n的整数数列,以及一个整数 k,请用快速选择算法求出数列从小到大排序后的第 k 个数。

输入格式

第一行包含两个整数 n 和 k。

第二行包含 n 个整数(所有整数均在 1∼1091∼109 范围内),表示整数数列。

输出格式

输出一个整数,表示数列的第 k 小数。

数据范围

1≤n≤100000

1≤k≤n

输入样例:
5 3
2 4 1 5 3
输出样例:
3

思路分析 :

一、

1、看到本题首先想到的是排序,先将这n个数进行排序,然后对排序结果的第k个数进行输出即可。

2、接下来就是要想我们要用什么排序。为了保证时间复杂度,对于冒泡、插入等排序这里就不考虑了。我们需要斟酒的是归并和快排这两种排序方式的选择,因为标准情况下两者的时间复杂度相同。都为O(nlogn)。当然,快排的时间复杂度不是很稳定,只有最理想的情况才是O(nlogn),最坏的情况是O(n^2),不过它的数学期望就是O(nlogn)。而归并排序的时间复杂度就是稳定的O(nlogn)。

二、

1、延续上面的时间复杂度分析,如果没有特殊情况我们应该选择归并排序。但是本题的要求并不是完全的排序而是只要选出从小到大排序后的第k个数就可以。

2、让我们把目光转到快速排序。快排是首先对整体进行排序:选择一个x,然后整体上把左边数变为小于x,右边大于x。后续:再分别同过递归对左右两边进行排序。看到这里实际上我们就知道了,既然快排整体上已经有序的,那么我们就可以通过对x左边数据量和k的大小比较 ,确定k是在左边子区间还是右边子区间。如此就只要对一边继续递归便可以。

下面我通过手写图来举个例子:

3、对快排这样改进后用于选择的算法称为:快速选择算法。其时间复杂度为O(n)。图解如下:

本人字真的很丑,勿喷,呜呜呜

代码如下:

#include<iostream>
using namespace std;
void quick_sort(int a[],int l,int r,int k){
    if(l==r)return;
    int i=l-1;
    int j=r+1;
    int x=a[(l+r)>>1];
    while(i<j){
        do i++;while(a[i]<x);
        do j--;while(a[j]>x);
        if(i<j) swap(a[i],a[j]);
    }
//到目前为止本算法和快速排序算法还是相同的,就是将一个大的区间分为两个整体大小确定的子区间
    int sl=j-l+1;//左子区间的长度
    if(sl>k) quick_sort(a,l,j,k);
    else quick_sort(a,j+1,r,k-sl);//k-sl是表示整体第k个数在右子区间中的第k-sl的位置
//这三行代码是对两个子区间进行选择,因为第k个数只会在其中一个区间,所以只需要对其中一个进行递归排序
}
int main(){
    int num,a=0;
    int b[100001]={0};
    cin>>num>>a;
    for(int i=0;i<num;i++){
        cin>>b[i];
    }
    quick_sort(b,0,num-1,a-1);
    cout<<b[a-1]<<endl;
}
相关文章
|
7月前
|
算法
【经典LeetCode算法题目专栏分类】【第2期】组合与排列问题系列
【经典LeetCode算法题目专栏分类】【第2期】组合与排列问题系列
|
7月前
|
算法
【经典LeetCode算法题目专栏分类】【第4期】BFS广度优先算法:单词接龙、最小基因变化、二进制矩阵中的最短路径
【经典LeetCode算法题目专栏分类】【第4期】BFS广度优先算法:单词接龙、最小基因变化、二进制矩阵中的最短路径
|
7月前
|
存储 算法
数据结构学习记录——图应用实例-六度空间(题目描述、算法思路、伪代码及解读、图解)
数据结构学习记录——图应用实例-六度空间(题目描述、算法思路、伪代码及解读、图解)
90 0
|
8月前
|
机器学习/深度学习 移动开发
【归并排序】【图论】【动态规划】【 深度游戏搜索】1569将子数组重新排序得到同一个二叉搜索树的方案数
【归并排序】【图论】【动态规划】【 深度游戏搜索】1569将子数组重新排序得到同一个二叉搜索树的方案数
|
8月前
|
存储 Python
Python实现案例讲解~计算斐波那斐数列的前n项
Python实现案例讲解~计算斐波那斐数列的前n项
|
算法
代码随想录算法训练营第二十六天 | LeetCode 39. 组合总和、40. 组合总和 II、131. 分割回文串
代码随想录算法训练营第二十六天 | LeetCode 39. 组合总和、40. 组合总和 II、131. 分割回文串
54 0
|
算法 Python
算法创作|规则数列计算解决方法
算法创作|规则数列计算解决方法
79 2
|
存储
图解LeetCode——56. 合并区间
图解LeetCode——56. 合并区间
139 1
|
算法 Java 网络架构
代码随想录训练营day27| 39. 组合总和 40.组合总和II 131.分割回文串
代码随想录训练营day27| 39. 组合总和 40.组合总和II 131.分割回文串
|
算法
算法设计与分析/数据结构与算法实验4:添加括号数目问题
算法设计与分析/数据结构与算法实验4:添加括号数目问题
195 0
算法设计与分析/数据结构与算法实验4:添加括号数目问题