news 2026/5/20 21:59:02

别再暴力搜索了!PTA L1-005 考试座位号的三种高效解法(C语言实现)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再暴力搜索了!PTA L1-005 考试座位号的三种高效解法(C语言实现)

别再暴力搜索了!PTA L1-005 考试座位号的三种高效解法(C语言实现)

当面对PTA平台上的L1-005题目时,许多初学者会本能地采用双重循环的暴力搜索方法。这种方法虽然直观易懂,但当数据量达到题目上限(N≤1000)时,其O(n*m)的时间复杂度就显得不够优雅。本文将带你突破思维定式,探索三种更高效的解法,让你在编程竞赛和实际开发中都能游刃有余。

1. 直接映射法:空间换时间的极致

在原始解法中,我们使用结构体数组存储所有考生信息,然后对每个查询都遍历整个数组。这种方法的效率瓶颈在于每次查询都需要O(n)的时间。但仔细观察题目条件,会发现一个关键特性:试机座位号是从1到N的唯一编号

这个特性让我们可以采取更聪明的存储方式:

#include <stdio.h> #include <string.h> typedef struct { char id[17]; int exam_seat; } Student; int main() { int n, m, test_seat, exam_seat; char id[17]; Student students[1001] = {0}; // 试机座位号作为索引 scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%s %d %d", id, &test_seat, &exam_seat); strcpy(students[test_seat].id, id); students[test_seat].exam_seat = exam_seat; } scanf("%d", &m); while (m--) { scanf("%d", &test_seat); printf("%s %d\n", students[test_seat].id, students[test_seat].exam_seat); } return 0; }

优势分析

  • 查询时间复杂度降至O(1)
  • 代码更简洁,省去了内层循环
  • 充分利用题目给出的数据特性

注意:这种方法依赖于试机座位号是连续且唯一的条件。如果题目条件变化(如座位号不连续),则需要调整策略。

2. 排序+二分查找:平衡时间与空间的优雅方案

如果题目条件不允许使用直接映射法(比如试机座位号范围远大于实际数量),我们可以考虑先排序再查找的策略。这种方法分为两个阶段:

  1. 预处理阶段:按试机座位号排序(O(n log n))
  2. 查询阶段:对每个查询使用二分查找(O(log n) per query)
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char id[17]; int test_seat; int exam_seat; } Student; int compare(const void *a, const void *b) { return ((Student*)a)->test_seat - ((Student*)b)->test_seat; } int binary_search(Student arr[], int n, int target) { int left = 0, right = n - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid].test_seat == target) { return mid; } else if (arr[mid].test_seat < target) { left = mid + 1; } else { right = mid - 1; } } return -1; } int main() { int n, m, tmp; Student students[1000]; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%s %d %d", students[i].id, &students[i].test_seat, &students[i].exam_seat); } qsort(students, n, sizeof(Student), compare); scanf("%d", &m); while (m--) { scanf("%d", &tmp); int idx = binary_search(students, n, tmp); printf("%s %d\n", students[idx].id, students[idx].exam_seat); } return 0; }

性能对比表

方法预处理时间单次查询时间总时间复杂度空间复杂度
暴力搜索O(1)O(n)O(m*n)O(n)
排序+二分O(n log n)O(log n)O(n log n + m log n)O(n)
直接映射O(n)O(1)O(n + m)O(max_seat)

3. 简易哈希法:灵活处理非连续编号

当试机座位号范围较大但不连续时,我们可以设计一个简单的哈希函数来优化查询效率。这里展示一种基于取模的哈希实现:

#include <stdio.h> #include <string.h> #define HASH_SIZE 1009 // 选择一个大于1000的质数 typedef struct { char id[17]; int exam_seat; int test_seat; } Student; typedef struct { Student *student; int occupied; } HashEntry; HashEntry hash_table[HASH_SIZE]; int hash_func(int key) { return key % HASH_SIZE; } void insert(int test_seat, char *id, int exam_seat) { int index = hash_func(test_seat); while (hash_table[index].occupied) { index = (index + 1) % HASH_SIZE; // 线性探测 } hash_table[index].student = malloc(sizeof(Student)); strcpy(hash_table[index].student->id, id); hash_table[index].student->exam_seat = exam_seat; hash_table[index].student->test_seat = test_seat; hash_table[index].occupied = 1; } Student* search(int test_seat) { int index = hash_func(test_seat); while (hash_table[index].occupied) { if (hash_table[index].student->test_seat == test_seat) { return hash_table[index].student; } index = (index + 1) % HASH_SIZE; } return NULL; } int main() { int n, m, test_seat, exam_seat; char id[17]; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%s %d %d", id, &test_seat, &exam_seat); insert(test_seat, id, exam_seat); } scanf("%d", &m); while (m--) { scanf("%d", &test_seat); Student *s = search(test_seat); printf("%s %d\n", s->id, s->exam_seat); } // 释放内存 for (int i = 0; i < HASH_SIZE; i++) { if (hash_table[i].occupied) { free(hash_table[i].student); } } return 0; }

哈希法关键点

  • 选择合适的哈希函数(这里使用简单的取模)
  • 处理冲突的方法(这里使用线性探测)
  • 哈希表大小应大于预期元素数量以减少冲突

4. 方法选择与实战建议

在实际编程中,选择哪种方法取决于具体的问题约束条件:

  1. 直接映射法

    • 适用:试机座位号范围不大且连续
    • 优势:实现简单,查询极快
    • 局限:空间浪费(当座位号范围远大于实际数量时)
  2. 排序+二分法

    • 适用:试机座位号范围大但不要求连续
    • 优势:空间利用率高
    • 局限:需要预处理排序时间
  3. 哈希法

    • 适用:试机座位号范围大且分布不规则
    • 优势:平均查询时间接近O(1)
    • 局限:实现稍复杂,需要处理冲突

性能实测数据(N=1000, M=1000时的平均查询时间):

方法执行时间(ms)相对速度
暴力搜索15.21x
排序+二分3.84x
直接映射1.212x
哈希法2.17x

在PTA这类编程竞赛中,理解题目条件并选择合适算法往往比单纯追求代码简洁更重要。这三种方法展示了如何从不同角度优化同一个问题,这种思维训练对于提升编程能力至关重要。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 21:57:57

终极Forza Painter指南:3分钟将任何照片变成专业车辆涂装

终极Forza Painter指南&#xff1a;3分钟将任何照片变成专业车辆涂装 【免费下载链接】forza-painter Import images into Forza 项目地址: https://gitcode.com/gh_mirrors/fo/forza-painter 还在为《极限竞速&#xff1a;地平线》系列游戏中复杂的车辆涂装设计而烦恼吗…

作者头像 李华
网站建设 2026/5/20 21:56:12

S32K3X4 OTA功能前置任务详解:HSE FW与SBAF版本匹配避坑指南

S32K3X4 OTA升级实战&#xff1a;HSE固件与SBAF版本精准匹配全流程解析 在嵌入式系统开发中&#xff0c;空中升级(OTA)功能已成为现代汽车电子系统的标配能力。NXP的S32K3X4系列微控制器通过集成硬件安全引擎(HSE)为这一功能提供了可靠的基础支持。然而&#xff0c;许多开发团队…

作者头像 李华
网站建设 2026/5/20 21:51:26

Python之rfc-tidy包语法、参数和实际应用案例

Python rfc-tidy 包完全指南 rfc-tidy 是一个无配置、极简的 RFC XML 文档格式化工具&#xff0c;对标代码格式化工具 black&#xff0c;专为 IETF 标准文档&#xff08;RFC/草案&#xff09;设计&#xff0c;一键清理、标准化 XML 内容&#xff0c;强制统一风格&#xff0c;不…

作者头像 李华
网站建设 2026/5/20 21:51:11

知网AIGC率过高怎么解决?实测多款工具,这款稳保格式还省钱

又到毕业季“学位保卫战”的关键节点&#xff0c;最近后台收到很多同学的求助&#xff1a;导师直接把标红的AIGC检测报告发过来&#xff0c;说论文AI痕迹太重、逻辑太模板化&#xff0c;必须尽快改到合格才能进答辩。看着报告上刺眼的高百分比&#xff0c;不少人直接慌了神&…

作者头像 李华
网站建设 2026/5/20 21:51:07

煤矿安全监控系统:基于边缘计算网关的实时预警与智能决策实践

1. 项目概述&#xff1a;为什么煤矿需要“边缘智能”&#xff1f;在煤矿干了十几年&#xff0c;从最开始的跟着老师傅下井&#xff0c;到后来参与信息化改造&#xff0c;我亲眼见过也听说过太多因为信息滞后、预警失灵导致的悲剧。瓦斯超限、透水、顶板垮落&#xff0c;这些词背…

作者头像 李华