寻找区间内第k小的数

sort排序

这是最直接暴力的方法,时间复杂度为O(nlogn)
直接排序,输出第k小的值即可

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

int n, k;
int a[N];

int main()
{ 
    cin >> n >> k;
    for (int i = 1; i <= n; ++ i) cin >> a[i];

    sort(a + 1, a + n + 1);

    cout << a[k] << endl;

    return 0;   
}

快速选择算法

时间复杂度的计算主要关注左右两个指针的移动,总次数为n+n2+n4+...,所以时间复杂度为O(n)
具体内容请见快速排序引申出的快速选择算法

大根堆

因为需要遍历每个元素O(n),且每个元素插入堆中的复杂度为O(logn),所以时间复杂度为O(nlogn),实际使用应该用不到,这里只是记录一种思想
本以为可以使用对顶堆解决这个问题,但是搞错了对顶堆的应用场景,然后误打误撞的发现大根堆也可以解决
假设寻找的为第k小的数,遍历所有数,将小于堆顶的数据插入堆,并始终维护堆的大小为k,最终堆顶元素即为第k小的数
我总是担心更小的数据会将目标元素提前弹出堆,但这种情况是不会发生的,假设能够发生这种情况,那么说明被弹出的目标元素在升序序列中是第k位之前的,所以才会因为堆满而被弹出。因为目标元素就是第k小的,所以我们的假设错误。因为没有进入堆的元素在有序序列中均是第k位之后的,所以最终堆顶元素就是有序序列中前k位元素最大的元素,即第k小的元素

#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 1e5 + 10;

int n, k;
int a[N];

int kth_element(int a[], int l, int r, int k)
{
    priority_queue<int> down; // 大根堆
    for (int i = l; i <= r; ++ i)
    {
        if (down.empty() || a[i] < down.top()) down.push(a[i]);

        if (down.size() > k) down.pop();
    }

    return down.top();
}
int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; ++ i) cin >> a[i];

    cout << kth_element(a, 1, n, k) << endl;

    return 0;
}
posted @   0x7F  阅读(92)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示