PAT手册

考纲

官方的介绍网站:https://www.patest.cn/introduction

甲级的考察内容

乙级要求:

1. 基本的C/C++的代码设计能力,以及相关开发环境的基本调试技巧;

2. 理解并掌握最基本的数据存储结构,即:数组、链表;

3. 理解并熟练编程实现与基本数据结构相关的基础算法,包括递归、排序、查找等;

4. 能够分析算法的时间复杂度、空间复杂度和算法稳定性;

5. 具备问题抽象和建模的初步能力,并能够用所学方法解决实际问题。

在达到乙级要求的基础上,还要求:

1. 具有充分的英文阅读理解能力;

2. 理解并掌握基础数据结构,包括:线性表

3. 理解并熟练编程实现经典高级算法,包括哈希映射并查集最短路径拓扑排序关键路径贪心深度优先搜索广度优先搜索回溯剪枝等;

4. 具备较强的问题抽象和建模能力,能实现对复杂实际问题的模拟求解。

近几年的考察题型汇总

PAT甲级考试总共有4道题,考察的类型分别如下(参考自浒鱼鱼的文章):

题号

考察知识点

1

字符串、素数、数学问题

2

链表、Hash函数、排序

3

图、并查集、(平衡、搜索)二叉树

4

LCA、树、拓扑排序、Dijkstra、堆

链表

甲级题目中大部分考察的静态链表,也就是使用数组的index作为指针。

考察题目:

序号

类型

题目

1

找到单词链表的共同后缀

2

对链表进行排序

第2道题参考了柳神的做法,用了一个取巧的办法,实际并没有对链表进行实质意义上的排序,而是记录了每个节点的自身的地址,实际上并没有对节点的地址进行调整。

对于二叉树的遍历方式有三种分别是:

前序(先序):根左右(根节点,左孩子,右孩子)

中序:左根右(左孩子,根节点,右孩子),如果是二叉搜索树,这个访问结果序列为有序序列

后序:左右根(左孩子,右孩子,根节点)

不加证明地给出,已知前序中序,或者中序后序可以唯一确定一颗二叉树,给定前序后序则不一定可以唯一确定一颗二叉树。

利用遍历序列重构二叉树

考察题目:

序号

类型

题目

1

依据后序中序输出前序

2

给定前序后序输出中序(不一定唯一)

3

给定前序中序,输出后序

第3道题比较“含蓄”地给出前序和中序,前序是其PUSH的序列,而中序是POP的序列。

代码实例:

考察题目:

序号

类型

题目

1

给定前序中序,输出后序

这道题的要求是输出后序访问中的第一个元素,参考柳神的代码中,我们可以得到不需要构建二叉树,直接输出这颗二叉树的后序思路,具体如下:

平衡二叉树

考察题目:

序号

类型

题目

1

求解平衡二叉树的根节点

2

创建平衡二叉树+判断完全二叉树

3

创建一颗二叉搜索树

这道题的本质就是构建一颗平衡二叉树,然后输出它的根节点即可,具体的代码解释,请查看这里

完全二叉树判断

并查集

考察的题目有:

序号

类型

题目

1

找到每个人归属的社群

2

计算家族房产

3

判断鸟儿是否属于同一棵树

寻找公共祖先

序号

类型

题目

1

寻找最近公共祖先

2

寻找最近公共祖先

首先对于“传统”思路建树,找结点路径,判断公共祖先,这个方法是肯定要会的,但是对于具体的题目,会有一些更为优化的算法。

这两道题中,第一道题采用,构建树,寻找两个节点的路径,在比较路径中的结点得到最近公共祖先会导致后面三个测试点超时,而第二道题使用上面这个思路则不会超时。

针对这两道题的解法都很巧妙,具体参考柳神的博客:11431151

补充得到树的root节点到叶子节点路径的方法:(下面这个查找到指定节点的路径)

中缀&后缀表达式

二叉查找树的结点删除

哈夫曼树

dfs+dijkstra 1087.All Roads Lead to Rome (30分)

Dijkstra算法

Floyd算法

拓扑排序

考察题型:

序号

类型

题目

1

判断是否为序列是否满足拓扑排序

算术运算

这两道题的核心是最大公约数的求法,使用辗转相除法

序号

类型

题目

1

有理数分数求和

2

有理数分数四则运算

最大公约数

最小公倍数

素数判断

考察题目:

序号

类型

题目

1

将数值分解成质因子相乘

闰年判断

进制转换

分数

大数计算

哈希表构建-平方探测法

注意的要点是,当H(key)被占用的时候,下一次的探测位置的计算公式为H(key) + k^2,和H(key) - k^2的平方,如果超过了哈希表的长度,那么就需要对表长取模。那么探测的次数要几次呢,如果一直没找到什么时候退出?这里的判断标准是k落在[0, tsize]内,如果k大于ksize时,一定无法找到了。

注意:这里查找的判断的范围是闭区间,[0, tsize],插入是[0, tsize)

考察题目:

序号

类型

题目

排序

关于排序,基本排序算法基本不会让你自己实现,所以对于选择排序,插入排序,快速排序这些,只需了解基本思想,能够知道实现流程即可。可能考察的题型,是链表的排序,就需要用到选择排序,或者插入排序的思想,因为链表不能直接跳转,无法直接使用sort函数。

冒泡排序

选择排序

插入排序

快速排序

考察题型:

序号

类型

题目

1

判断序列元素是否可以作为pivot

判断的思想是这样,一个元素能够作为pivot的条件是,序列的左半部分比pivot小,右半部分比pivot大,关键点在于,这个选为pivot的数值在一轮排序中是处于最后位置的,这个是这道题的核心。如果直接判断左半部分和右半部分满不满足条件的话,测试用例会超时,因为这样是O(n2) O(n^2)的时间复杂度。

这道题的其他解法,参考: DedicateToA 的这篇文章

归并排序

考察的题型有:

序号

类型

题目

1

判断是否是插入排序,归并排序的序列

2

判断是否是插入排序,堆排序的序列

这两道题都是给定了两个序列,一个是未排序初始序列,另一个是排序为完成的序列,判断是采用哪种排序方式,然后给出下一轮次的排序结果。

判断是否是插入排序的方法:

这两道题可以选择取巧的方式,因为只判断两种排序方式,不是其中一种,那就一定是另外一种了,所以只需要判断一种排序方式即可,相比之下,插入排序的判断方式是比较快的,所以只要判断是否是插入排序,不是的话一定就是另外一种排序方式了。

堆排序

深度优先搜索和广度优先搜索

序号

类型

题目

这三道题的类型一致,都是深度优先搜索,只不过根据题目的要求不同判断条件不同,万变不离其宗,可以对比着学习。

背包问题

n件物品,每件物品的重量为w[i],价值为c[i],现在要选出若干件物品放入一个容量为V的背包中,使得选入背包的物品重量不超过容量V的前提下,让背包中共的物品价值最大。

总结:这个问题给了一类常见的DFS问题的解决办法,即给定一个序列,枚举这个序列的所有子序列(可以不连续)。

比如说,从N个整数中选择K个数,使得这个K个数的和为X,如果有多个方案,选择元素平方和最大的一个。

有趣的算法问题

全排列

给定一个数组为1~N,如果输出它的全排列呢?(《算法笔记》P115)

拓展问题:如何输出给定数据的全排列呢?例如输入['a', 'b', 'c'],[11, 12, 13],我的思路:既然我们可以求出1~N的全排列,把这些全排列作为index下面,然后依据下标index输出输入的['a', 'b', 'c']即可。

拓展N皇后问题

序号

类型

题目

1

判断是否满足N皇后的排列序列

这道题难度不大,核心就是判断N皇后的位置不在对角线以及同一行即可。

简单概述下N皇后问题,就是将N皇后放在N×N的棋盘上,要求是皇后不能处在同一排,同一列以及对角线上,目标是求出这样的排列方式有哪些。

这个问题为什么和全排列有关系呢,是这样的,每个N皇后的摆放位置可以是1N的位置,那么在棋牌上从左到右来看的话,就是每个皇后的位置都是从1~N中选择一个数值,这样满足了不是同一列,那么为了满足不是同一排,那么每个皇后选择的位置是不同的,这样得到的最终数值就是一个全排列,现在唯一不满的就是对角线了,所以只需要在全排列代码的基础上判断不处于对角线即可。

日期处理

输出两个日期的差值,两个日期之间相差多少天,思路是对小的日期进行++,直到等于大的日期。

快速幂

n!有多少个质因子P

组合数

利用公式Cnm=Cn1m+Cn1m1C^m_n = C_{n-1}^m +C_{n-1}^{m-1},这部分内容挺多,直接参考《算法笔记》P183

注意!!

  1. 使用scanf读入字符时要注意,前面加个空格,原因参考这里

2. i++和++i

在代码里面,我们可以看到for循环的第三个表达式有两种写法,i++和++i,那么这两个区别是什么呢,要用哪一个呢?结论是用哪一个都可以,但是效率上有一点点差别,但是随着现代编译器和计算机性能的发展,这个差别几乎可以不考虑。那么差别在哪里呢?

3. map的神奇之处

map可以直接访问未插入的元素,比如下面的代码:

4. 数值的表示范围

题目中会给出数据的取值范围,我们需要判断相应的变量类型是否可以放得下,所以记住各个变量的表示范围是很有必要的。题目中一般给的是10的几次方的形式,所以大致范围需要重点关注。其他类型属于常规,可直接参考《算法笔记》P7.

类型

取值范围

大致范围

int

-2147483548~+2147483647(231-2^{31} ~+2311 +2^{31}-1)

2×109-2 \times 10^{9} ~2×1092 \times 10^{9}

long long

263-2^{63} ~+2631 +2^{63}-1

9×1018-9 \times 10^{18} ~9×10189 \times 10^{18}

5. 输入一行单词的小技巧

6. 什么叫做剪枝?

和这个相关的有几个说法:

暴力法:枚举所有的情况,然后判断每一种情况是否合法,这种做法是非常朴素的,没有优化的算法

回溯法:如果到达递归边界的某层,由于一些事情导致已经不需要往任何一个子问题递归,就可以直接返回上一层,这种做法称之为回溯法

剪枝:在DFS中,通过题目限制条件来减少DFS计算量的方法称之为剪枝。至于为什么叫做剪枝,是因为DFS的遍历就如果如果树的先根遍历,剪枝就是去掉不满足条件的子树,所以称之为剪枝。《算法笔记》P305

7. STL中queue的注意事项

8. 要点

要注意数据的取值范围!选择正确的数据类型!

注意数据中是否可能出现重复数据,使用大于小于,还是大于等于,小于等于

注意下标是从0开始还是从1开始!

使用printf和scanf进行输出输入,时间和cin和cout差别很大!尽量不适用cin和cout

参考材料

  1. 《算法笔记》胡凡.曾磊.著

  2. 《算法笔记 - 上机训练实战指南》 胡凡.曾磊.著

  3. 浒鱼鱼的CSDN博客

Last updated

Was this helpful?