学习笔记:查找数组第K小的数(去重排名)

一、题目信息

1. 题目描述

查找一个数组的第K小的数,相同数值算同一个排名(如数组 [2,1,3,4,5,2] 的第3小数为3)。

  • 时间限制:1000 ms
  • 内存限制:256 mb
  • 题目来源:北京邮电大学

2. 输入输出格式

输入描述 输出描述
多组数据,每组输入: 1. 数组长度 n(1≤n≤1000) 2. n 个整数 3. 目标排名 k 输出每组数据的第 k 小整数(题目保证 k 合法)

3. 样例

复制代码
输入:
6
2 1 3 5 2 2
3

输出:
3

二、核心解题思路

1. 整体流程

多组输入
读取n、数组、k
数组升序排序(qsort)
遍历排序数组,去重计数
找到第k个不同数,输出

2. 关键步骤解析

  1. 排序 :用 C 标准库 qsort 快速排序(时间复杂度 O(n log n)),替代冒泡排序提升效率;
  2. 去重计数:排序后相同数值连续排列,遍历数组时仅当当前数与前一个数不同,才将排名计数 +1;
  3. 终止条件:计数等于 k 时,立即输出当前数并结束(减少无效遍历)。

三、完整代码(优化版)

c 复制代码
#include <stdio.h>
#include <stdlib.h>

// qsort比较函数:整型升序(防整数溢出)
int compare_int(const void *a, const void *b) {
    int num1 = *(const int *)a;
    int num2 = *(const int *)b;
    // 三目运算符替代 num1-num2,避免 INT_MAX - (-1) 溢出
    return (num1 > num2) ? 1 : (num1 < num2) ? -1 : 0;
}

int main() {
    int n, k;
    // 多组输入:scanf返回1表示成功读取n,直到输入结束
    while (scanf("%d", &n) == 1) {
        int arr[1001] = {0}; // n≤1000,固定数组满足内存限制
        // 读取n个整数
        for (int i = 0; i < n; i++) {
            scanf("%d", &arr[i]);
        }
        scanf("%d", &k); // 读取k值

        // 快速排序:数组首地址、元素数、单个元素大小、比较函数
        qsort(arr, n, sizeof(int), compare_int);

        // 去重计数找第k小
        int count = 1;    // 初始排名:第一个数为第1小
        int result = arr[0];
        for (int i = 1; i < n; i++) {
            if (arr[i] != arr[i-1]) { // 遇到不同数,排名+1
                count++;
                result = arr[i];
                if (count == k) break; // 找到目标,提前退出
            }
        }

        printf("%d\n", result); // 输出结果
    }
    return 0;
}

四、核心知识点

1. qsort 函数(重点)

参数 说明
void *base 待排序数组首地址(void* 适配任意类型)
size_t nitems 数组元素个数(sizeof(arr)/sizeof(arr[0]) 计算)
size_t size 单个元素字节大小(如 sizeof(int))
compar 比较函数指针,返回值规则: 负数→a在前(升序)、0→相等、正数→a在后(降序)

2. 防溢出的比较函数

  • 错误写法:return num1 - num2;(可能溢出,如 num1=INT_MAX,num2=-1);
  • 正确写法:return (num1 > num2) ? 1 : (num1 < num2) ? -1 : 0;

3. 多组输入处理

  • while (scanf("%d", &n) == 1) 循环,直到输入结束(控制台输入 Ctrl+Z/文件结束)。

4. 去重计数逻辑

排序后数组 [1,2,2,2,3,5]
计数过程 1(count=1)→ 2(count=2)→ 3(count=3)
结果 3(第3小)

五、易错点总结

  1. qsort 参数错误 :误将 size 传成数组总字节数(正确应为单个元素字节数);
  2. 比较函数溢出 :直接用 num1 - num2 导致整数溢出;
  3. 多组输入遗漏:未用 while 循环处理多组数据;
  4. 计数逻辑错误 :在 if(count==k) 外未提前 break,导致无效遍历。

六、优化点

  1. 效率:qsort 比冒泡排序(O(n²))效率更高,n=1000 时优势明显;
  2. 内存 :固定数组 int arr[1001] 满足题目 n≤1000 的限制,无需动态分配;
  3. 性能:找到第 k 个值后立即 break,避免遍历整个数组。
相关推荐
星云POLOAPI2 小时前
大模型API调用延迟过高?深度解析影响首Token时间的五大因素及优化方案
人工智能·python·算法·ai
88号技师2 小时前
2026年1月一区SCI-波动光学优化算法Wave Optics Optimizer-附Matlab免费代码
开发语言·算法·数学建模·matlab·优化算法
旖旎夜光2 小时前
Linux(6)(下)
linux·学习
明朝百晓生3 小时前
强化学习[chapter8] [page17] Value Function Methods
人工智能·算法
叫我莫言鸭3 小时前
关于word生成报告的POI学习
学习·word
马剑威(威哥爱编程)3 小时前
【鸿蒙学习笔记】基于HarmonyOS实现申请Push Token的功能
笔记·学习·harmonyos
万变不离其宗_83 小时前
华为高斯(gauss)数据库使用笔记
笔记
jjjxxxhhh1233 小时前
2025年底 -对工作做个跨年总结
学习
POLITE33 小时前
Leetcode 56.合并区间 JavaScript (Day 6)
算法·leetcode·职场和发展