学习笔记:查找数组第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(arr0) 计算)
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,避免遍历整个数组。
相关推荐
YH55269844 小时前
GPT‑5.6 Sol 原本支持 1M 上下文,Codex 现已放开此前限制,如何看待这次调整?
java·jvm·人工智能·gpt·算法·chatgpt
chushiyunen4 小时前
欧洲地理笔记
笔记
吃着火锅x唱着歌4 小时前
Effective C++ 学习笔记 条款43 学习处理模板化基类内的名称
c++·笔记·学习
weixin_431600446 小时前
Agent Workflow 学习向:Code 节点,比模板更强的变量加工
后端·python·学习·ai·
遥感知识服务6 小时前
从局部阈值、双极化到暗地表剔除:NASA OPERA DSWx-S1全球动态水体算法拆解
大数据·人工智能·深度学习·神经网络·算法·机器学习
晚风醉蝶6 小时前
1-13-TimSort
算法
ZJU_统一阿萨姆6 小时前
【算子开发】算子融合与Softmax_LayerNorm实现
人工智能·算法·语言模型·硬件架构
Xuanzang Road6 小时前
第 40 届学习强企玄奘路戈壁挑战赛:在绝境中重塑自我
学习
tju新生代魔迷7 小时前
Python学习日记3
学习
叩码以求索8 小时前
浅谈:前序遍历反转法求解N叉树的后序遍历
算法