2.Acwing基础课第786题-简单-第k个数

2.Acwing基础课第786题-简单-第k个数

题目描述

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

输入格式

第一行包含整数 n 和 k。

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

输出格式

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

数据范围

1≤n≤100000

输入样例

5 3
2 4 1 5 3

输出样例

3

思路解析:

算法:快速排序 ( Quick Sort )

时间复杂度:O(nlog(n))

解题思路:

1.使用快速排序,把数组从小到大进行排序
2.然后直接输出对应下标的数(记得减一)

代码:

快排
#include <iostream>
using namespace std;

const int N = 1e5+10;
int q[N];
int n, m;

void quick_sort(int q[], int l, int r)
{
    if(l >= r)  return;
    
    int i = l-1, j = r+1, x = q[l+r>>1];
    while(i < j)
    {
        do i++; while(q[i] < x);
        do j--; while(q[j] > x);
        if(i < j)  swap(q[i], q[j]);
    }
    
    quick_sort(q, l, j), quick_sort(q, j+1, r);
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i++)  cin >> q[i];
    
    quick_sort(q, 0, n-1);
    
    cout << q[m-1] << endl;
    
    return 0;
}
选择
#include <iostream>
using namespace std;

// 定义数组最大长度:1e5+10 适配题目中常见的10万级数据规模
const int N = 1e5 + 10;
// n:数组元素个数,k:要找的第k小的元素
int n, k;
// q数组:存储待处理的整数序列
int q[N];

/**
 * @brief 快速选择算法(Quick Select):在数组q的区间[l, r]中找到第k小的元素
 * @param q 待处理的数组(全局数组也可,显式传参更规范)
 * @param l 当前递归处理的区间左边界
 * @param r 当前递归处理的区间右边界
 * @param k 目标:找当前区间内第k小的元素
 * @return int 找到的第k小的元素值
 */
int quick_sort(int q[], int l, int r, int k)
{
    // 递归终止条件:当区间[l, r]只剩一个元素时,该元素就是当前区间要找的第k小元素
    if (l >= r) return q[l];

    // 初始化双指针:
    // i = l-1 → 左指针初始在区间左边界左侧,后续向右移动
    // j = r+1 → 右指针初始在区间右边界右侧,后续向左移动
    // x = q[l+r>>1] → 取区间中间位置的元素作为基准值(避免有序数组导致算法退化)
    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    
    // 双指针扫描区间,进行分区操作:把<=x的元素放到左区间,>=x的元素放到右区间
    while (i < j)
    {
        // 左指针向右移动,直到找到第一个 >= x 的元素(跳过所有 < x 的元素)
        do i++; while (q[i] < x);
        // 右指针向左移动,直到找到第一个 <= x 的元素(跳过所有 > x 的元素)
        do j--; while (q[j] > x);
        // 如果两指针未相遇,交换这两个元素,保证左区间<=x,右区间>=x
        if (i < j) swap(q[i], q[j]);
    }

    // 计算左分区[l, j]的元素个数(j - l + 1)
    // 判断第k小的元素在左分区还是右分区:
    if (k <= j - l + 1)
        // 左分区元素数 >= k → 第k小在左分区,递归处理左分区[l, j]
        return quick_sort(q, l, j, k);
    else
        // 左分区元素数 < k → 第k小在右分区,递归处理右分区[j+1, r]
        // 且目标变为找右分区的第 (k - 左分区元素数) 小的元素
        return quick_sort(q, j + 1, r, k - (j - l + 1));
}

int main()
{
    // 输入:数组长度n + 要找的第k小元素
    cin >> n >> k;
    // 输入n个整数,存入q数组
    for (int i = 0; i < n; i++) cin >> q[i];
    
    // 调用快速选择函数,找q[0..n-1]中第k小的元素,并输出结果
    cout << quick_sort(q, 0, n - 1, k) << endl;
    
    return 0;
}
posted @ 2023-08-22 18:15  CodeMagicianT  阅读(64)  评论(0)    收藏  举报