简介:这份资源是面向计算机专业初学者与编程入门学习者的程序设计基础 OJ 题库合集,源自南京信息工程大学(NUIST)的在线评测平台,适合正在学习 C++ 或 Java 语法、希望系统训练算法设计与数据结构应用的学生使用。压缩包整体约 482.72MB,以 zip 格式打包,内容围绕 OJ 平台做题场景组织,涵盖排序、搜索、图论、动态规划等经典算法题目,以及数组、链表、栈、队列、树、哈希表等数据结构的实践练习,并可能包含做题工作目录中的源代码、测试数据与编译运行结果,便于回顾解题思路、对照验证与查漏补缺。目前已有 754 人学习下载,说明该题库在入门训练中具有一定参考价值。读者可借助它熟悉在线评测的实时反馈机制,在反复提交与修正中提升编程技能、算法设计能力和独立解决问题的能力,为后续软件开发等方向打下基础。
1. 从一道“看着会、写出来全错”的题说起
程序设计基础这门课的 OJ 题库,最容易让人翻车的不是难题,而是那种题干三行、样例两组、你觉得自己十分钟能秒掉的题。输入两个整数求和,看着像送分,真交上去却可能连着吃三个 WA:没处理多组输入、没注意数据范围溢出、输出格式多了一个空格。程序设计基础 OJ 题库的判题逻辑是黑匣子,它不告诉你错在哪,只回你一个结果。所以这场考试真正考的不是“你会不会写循环”,而是你能不能在看不到测试点的情况下,把边界、格式、数据类型一次性想全。这份题库适合正在准备程序设计基础机考、课程 OJ 刷题、以及需要靠刷题稳住平时分和期末分的人。拿分的核心逻辑只有一句:先把高频题型的套路背熟,再用易错点清单反向检查自己的代码。
2. 考点分布:程序设计基础 OJ 到底在考哪几类题
2.1 五类高频题型与分值权重
程序设计基础 OJ 题库的题目数量看着多,但真正反复出现的题型就那么几类。把题库按考点归类之后,大致可以分成下面五块,权重从高到低排列:
| 题型模块 | 典型题面特征 | 占比感受 | 拿分难度 |
|---|---|---|---|
| 输入输出与格式控制 | 多组输入、保留小数、对齐输出 | 最高 | 低但极易失分 |
| 分支与循环 | 分段函数、累加累乘、图形打印 | 高 | 中 |
| 数组与字符串 | 排序、查找、字符统计、回文判断 | 高 | 中 |
| 函数与递归 | 阶乘、斐波那契、进制转换 | 中 | 中高 |
| 基础算法入门 | 枚举、简单模拟、素数判断 | 中 | 高 |
这张表最值得盯的是第一行。很多人复习时把时间全砸在算法上,结果丢分最多的是输入输出。OJ 判题是逐字节比对,你多输出一句“请输入两个数”,直接判错。这类题的复习优先级应该排在最前面,因为它投入产出比最高,练半小时就能稳住一批分。
2.2 真题演练:多组输入求和为什么总 WA
先看一道最典型的题:不断读入两个整数,输出它们的和,直到文件结束。很多人第一版写成这样:
#include <stdio.h> int main() { int a, b; scanf("%d %d", &a, &b); // 只读一次 printf("%d\n", a + b); return 0; }这段代码在样例上能过,因为样例通常只给一组数据。但 OJ 的测试文件里往往塞了多组,判题程序会一直喂数据,你的程序读完第一组就退出了,后面的全没处理,结果就是 WA。正确写法是把读入放进循环条件里:
#include <stdio.h> int main() { int a, b; // scanf 返回成功读入的变量个数,读到文件末尾返回 EOF while (scanf("%d %d", &a, &b) == 2) { printf("%d\n", a + b); } return 0; }这里的关键参数是scanf的返回值。它返回成功赋值的变量个数,读两个整数成功就是 2,遇到文件结束返回EOF(通常是 -1)。所以循环条件写== 2比写!= EOF更稳,因为如果输入里混进了非数字字符,scanf会返回 0 或 1,!= EOF判断不出来,容易死循环。面试官或出题人看这类题,最想确认的就是你知不知道“多组输入”和“单组输入”的区别,以及你会不会用返回值控制循环。
2.3 真题演练:图形打印题的循环边界怎么定
图形打印是分支循环模块的常客,典型题是输出一个 n 行的直角三角形或菱形。以 n 行左对齐星号三角为例:
#include <stdio.h> int main() { int n; scanf("%d", &n); for (int i = 1; i <= n; i++) { // 控制行数 for (int j = 1; j <= i; j++) { // 每行输出 i 个星号 printf("*"); } printf("\n"); // 每行结束换行 } return 0; }外层循环变量i从 1 到 n,代表当前是第几行;内层循环从 1 到 i,代表这一行要打几个星号。这类题翻车最多的地方是边界:i <= n写成i < n少一行,内层写成j <= n变成矩形。答题时的通用套路是先手算 n=3 和 n=1 两种情况,把每行的循环次数写在纸上,再对照代码。如果题目要求右对齐或者倒三角,就在每行前面补空格,空格数是n - i,这个规律记住能省很多推导时间。
3. 高频考点:数组、字符串与函数的答题模板
3.1 数组题:排序与查找的固定写法
数组模块最高频的两类题是排序和查找。排序题通常不限制算法,但数据量小的时候冒泡和选择排序足够用,写起来不容易错。以冒泡排序升序为例:
#include <stdio.h> int main() { int n, a[100]; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } // 冒泡排序:每轮把最大的元素推到末尾 for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1 - i; j++) { if (a[j] > a[j + 1]) { int t = a[j]; a[j] = a[j + 1]; a[j + 1] = t; } } } for (int i = 0; i < n; i++) { printf("%d ", a[i]); } return 0; }内层循环的上界是n - 1 - i,因为每轮结束后末尾已经有 i 个元素排好了,不用再比。这个- i是很多人漏掉的地方,漏了不会错,但会多做无用比较。查找题分两种:顺序查找直接遍历,二分查找要求数组有序。二分查找的模板要背熟,尤其是mid = (left + right) / 2和left = mid + 1、right = mid - 1的更新方向,写反一个就是死循环。这类题面试官最想听的是你能不能说出“二分的前提是有序”,以及边界更新为什么不能写成left = mid。
3.2 字符串题:字符统计与回文判断
字符串题在 OJ 里通常以字符数组的形式出现,高频考法是统计某类字符个数、判断回文、大小写转换。以统计一行字符中字母、数字、空格和其他字符的个数为例:
#include <stdio.h> int main() { char s[200]; int letter = 0, digit = 0, space = 0, other = 0; fgets(s, sizeof(s), stdin); // 读入一整行,包含空格 for (int i = 0; s[i] != '\0'; i++) { if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) letter++; else if (s[i] >= '0' && s[i] <= '9') digit++; else if (s[i] == ' ') space++; else if (s[i] != '\n') // 换行符不计入其他字符 other++; } printf("%d %d %d %d\n", letter, digit, space, other); return 0; }这里用fgets而不是scanf("%s"),因为scanf遇到空格就停,统计不了空格。fgets会把换行符也读进来,所以判断其他字符时要排除\n,这个细节是字符串题最常见的失分点。回文判断的套路是双指针,一个从头一个从尾往中间靠,遇到不相等就判否,注意大小写是否敏感要看题面要求。
3.3 函数与递归:把重复逻辑抽出去
函数题的考法通常是“定义函数实现某功能”,比如写一个判断素数的函数、求最大公约数的函数。递归题则以阶乘、斐波那契、汉诺塔为代表。以递归求阶乘为例:
#include <stdio.h> long long fact(int n) { if (n == 0 || n == 1) return 1; // 递归出口 return n * fact(n - 1); // 递归调用 } int main() { int n; scanf("%d", &n); printf("%lld\n", fact(n)); return 0; }返回值用long long是因为阶乘增长极快,13 的阶乘就超过 int 范围了。递归题必须写出口,否则栈溢出。这类题答题时的思路是:先写出口,再写递推关系,最后检查数据范围。面试官问递归,往往接着会问“递归和循环的区别”,标准答法是递归代码简洁但有栈开销,循环效率高但代码可能啰嗦,实际做题时数据量大优先循环。
4. 易错点:五类最常见的失分题与纠正方法
4.1 整数溢出:int 装不下还在用 int
错在哪:累加、阶乘、斐波那契这类题,结果很容易超过 int 的表示范围,代码逻辑全对但结果变成负数。为什么错:int 通常是 32 位,最大约 21 亿,看着很大,但 20 的阶乘就远超了。怎么答对:先看题目给的数据范围,凡是涉及累乘、大数累加,直接上long long,输出用%lld。养成习惯:看到“求和”“阶乘”“斐波那契”三个词,先想数据类型。
4.2 浮点数比较:用 == 判断相等
错在哪:判断两个浮点数是否相等时写if (a == b),结果该相等的时候判不相等。为什么错:浮点数在计算机里是近似存储,0.1 + 0.2 不等于 0.3。怎么答对:用差值绝对值判断,if (fabs(a - b) < 1e-6),1e-6 是精度阈值,题目要求保留几位小数就取比它更小的量级。这类题面试官想听的就是“浮点数不能直接比相等”这句话。
4.3 数组越界:循环多跑了一次
错在哪:数组大小定义成a[10],循环写for (i = 0; i <= 10; i++),访问了a[10]。为什么错:C 语言数组下标从 0 开始,a[10]的合法下标是 0 到 9,<=导致越界,可能改掉别的变量值,表现为“玄学错误”。怎么答对:循环条件统一用< n,数组定义时多开几个空间留余量,比如题目说 n 最大 100,就定义a[105]。
4.4 输出格式:多一个空格少一个换行
错在哪:题目要求每个数后面跟一个空格,最后一个数后面不能有空格,很多人统一输出"%d ",最后一个数后面多了空格,判题机逐字节比对直接 WA。为什么错:OJ 不智能,它不会帮你忽略行末空格。怎么答对:用“第一个数单独输出,后面的数前面加空格”的写法,或者判断是不是最后一个元素。这类题没有技巧,就是交之前把样例输出和自己的输出逐字符对一遍。
4.5 多组输入没读完就退出
错在哪:题目说“输入包含多组测试数据”,代码只读一组。为什么错:没理解 OJ 的测试文件是连续喂数据的,程序要一直处理到文件结束。怎么答对:用while (scanf(...) == 期望个数)包住整个处理逻辑,这是固定模板,背下来直接用。
5. 答题节奏:从读题到提交的四步检查法
机考现场最亏的不是不会做,是会做但没时间检查。我的习惯是把每道题拆成四步走,这套流程是从多次翻车经验里逼出来的。
第一步,读题先圈三样东西:数据范围、输入组数、输出格式。数据范围决定用什么类型,输入组数决定要不要写循环读入,输出格式决定空格和换行怎么打。这三样圈完,题目的坑基本就露出来了。很多人上来就敲代码,敲到一半发现要处理多组输入,回头改结构,时间全浪费在这。
第二步,先在纸上写伪代码,尤其是循环的起止条件。图形打印、数组遍历这类题,边界写错是最高频的失分原因。纸上写i从几到几、内层循环跟谁有关,比在编辑器里反复试错快得多。
第三步,写完代码先自己造三组数据:最小规模(n=1)、普通规模、边界规模(n 取最大值)。用这三组数据手动跑一遍,重点看循环进不进得去、数组下标有没有越界、输出格式对不对。这一步能拦下大部分低级错误。
第四步,提交前对照样例输出逐字符比。不是看“差不多”,是看空格数量、换行位置、小数点位数。OJ 的判题逻辑是黑匣子,但它对格式的苛刻是确定的,你只能靠肉眼对齐。
| 检查步骤 | 检查对象 | 常见问题 |
|---|---|---|
| 读题圈重点 | 数据范围、组数、格式 | 漏看“多组输入” |
| 纸上写边界 | 循环起止、数组下标 | 多跑一次或少跑一次 |
| 自造三组数据 | 最小、普通、边界 | 溢出、越界 |
| 对照样例 | 空格、换行、小数位 | 行末多空格 |
押题方向上,输入输出格式控制、数组排序查找、简单递归这三块几乎每套卷子都会出现,复习时间应该按这个顺序分配。基础算法入门里的素数判断和枚举,考法固定,把模板背熟就能拿分,不用深挖。
从那以后我每次交题前都强制走一遍这四步,尤其是第一步圈重点,宁可多花两分钟读题,也不在提交后对着 WA 猜原因。希望帮到你。
本文还有配套的精品资源,点击获取