PAT甲级(Advanced)解题记录
历时:20190627-20190730
github代码仓库:
传送门:地址
按解题时间:
按题目顺序:
1001错误一个,记得考虑特殊情况0;
1002错误一个,注意判断浮点数的时候,用差的绝对值比较呀fabs(coeff[i]-0.0)>10e-5
漏掉了一个fabs导致一个用例一直错误。
1003 dijkstra最短距离算法。用邻接表和邻接矩阵各写了一遍。注意算法书上的总结P377:这种题的三种拓展要求(点权、线权、最短个数)都可以通过在优化路线的时候增加一个数组来输出,如果要求最短距离的路径,也可以增加一个pre,保存每一个节点的前置路径。
1004统计每一层叶子节点个数。EZ
1005①错误一个,记得考虑0;②PAT编译器不支持gets
,整行读取使用c++的cin.getline(str,len)
,加上 #include<iostream> using namespace std;
The function std::gets()
was deprecated in C++11 and removed completely from C++14.
1006 EZ.
1007全是坑,自己思路没错但是输出格式错误。注意各种0的情况。动态规划方法
1008读题认真。while(scanf("%d,&n)!=EOF)
编译器端失灵,可能和没法手动Ctrl+Z有关。学到一个新方法
do{……}while((c=getchar())!='\n')
1009正常做。注意输出格式。在不溢出的情况下,申请数组可以尽量大些,基本也不影响超时。
1010二分法的进制转换【膜柳神】一个很巧妙的点,如果转换成十进制的数,超过了long long上限,会变成负数,也是大的表现。这一点得10分。学习代码思路:
long long findradix(string c,long long n){
char it=*max_element(c.begin(),c.end());//最大元素max_element返回的是迭代器。
long long low=(isdigit(it)?it-'0':it-'a'+10)+1;//最小进制要比最大元素大1;
long long high=max(n,low);
while(low<=high){
long long mid=(low+high)/2;
long long t=any2dec(c,mid);
if(t<0||t>n) high=mid-1;//t<0;转换的进制溢出,也是大于n
else if(t==n) return mid;
else low=mid+1;
}
return -1;
}
1011EZ.
1012学习使用C++的sort
,算法笔记P235,sort(a,a+N,cmp);
1013图的dfs遍历求连通图个数。
1014 第三还是第四次做,终于AC了,排队模拟题,难顶。
1015测试用例2折腾半天,质数的判断,最好还是吧0,1,2单独列出来返回结果。0,1不是质数(也不是合数,2是质数)质数英文prime number。
1016重写了一遍当时调试了很久的代码,一遍过了可还行。
1017 模拟题,本来写的好好的,因为最后结果浮点数的问题,怀疑自己的思路检测了一个多小时。double res=int/int
是错误的…int/int直接就是整型保留了。
1018自行车管理系统,人都做傻了25/30。dijkstra求最短距离,最短距离路径又很多条,沿路又要平衡权值,没想出来怎么一边走一边优化,只好把所有最短路径都输出再遍历计算一遍需要带的自行车数量。还是未知原因没能AC 【0726更新】和1087做法一样,用pre保存所有最短路径,dfs以后挨个计算。一遍过~用时30分钟。
1019EZ.注意特殊情况0即可。
1020二叉树,基础题,跟着算法笔记复习了一遍前中后层次四种遍历,以及利用前中、中后遍历数据构建二叉树的算法。代码全部贴进去了。代码
1021无环图可以看作树,因为只有n-1条边,无环(连通图数量为1)肯定就是树,所以只用bfs即可,第一次bfs先完全搜索判断有几个连通图,只有一个连通图再对每一个节点作为根节点进行bfs得到最深深度。最后比较输出。
1022基础输入输出题目,复杂但是不难,练速度。学一下getchar();scanf("%[^\n]",keywordtemp);
这种整行读取的方法。
1023字符串数字翻倍;EZ
1024 回文数判读+大数字相加(字符串string操作)string
相关操作需要巩固(reverse
函数)
1025STL sort结构体排序基础题。注意一下vector的sort函数写法sort(a.begin(),a.end(),cmp);
距离就只能begin+n这样了;
1026 模拟题。细节。冷静的时候再练吧。。25/30【0727】顶不住,抄了柳神代码。传送门
1027EZ.
1028EZ sort排序基础题
1029内存溢出题,题目限制1.5MB,然后吓唬你所有数据不超过long int
,实际上按照最大规模2^10e5个long int(每个8字节,就是1.6MB了?,所以答案不可能是long int
,事实上所有测试数据也都不超过int。【似乎还是有问题,第一个序列就一个long int数据咋搞。】
学习点:define MAX 0x7fffffff
,再也不用记2的32次方-1
是多少了。
1030 标准dijkstra
1031EZ
1032 地址映射 T.T这么简单的题做2个小时。好好学学别人的思路。很多东西都不需要的不用都保存下来。灵活使用数组的序号作为标志。
1033贪心算法思路很重要!需要再练一次
1034 第一次写图的题。感觉写的太复杂了。
1035水题,代码10分钟写完,调试半个小时,输入输出的特殊情况读题!读题!!读题!!!
1036EZ.
1037 排序+简单贪心。两个指针搜索,多条件退出的写法优化,柳神的代码思路:
int i=0,j=0; while(i<c&&j<p&&arrc[i]<0&&arrp[j]<0){ sum+=arrc[i]*arrp[j]; i++;j++; } i=c-1;j=p-1; while(i>=0&&j>=0&&arrc[i]>0&&arrp[j]>0){ sum+=arrc[i]*arrp[j]; i--;j--; }
1038一段段的数据排序得最小总数,cmp函数占一半,有机会再看看别人得思路。坑:测试点2全是0,最后也要输出一个0,如果是多个数0,前面得0都不输出。
1039哈希,固定长度的字符串很容易转换为数字题目不难但是做了很久T.T
1040 字符串的回文序列的最大值。类似于abba这种偶数的没有中心点的要么用两种方法重复算,要么用一个神奇的方法,每个字符后面加一个-1(字符转换为int)这样就肯定是奇数了。
1041火星unique彩票,队列
1042EZ 洗牌,注意可能有多个环链,所以没法排序按照洗的次数直接整体位移,先分组太麻烦了,因为只有54张牌所以时间复杂度高不起来,直接基础思路做就ok。
1043 判断数列是否为二叉树的前序遍历结果,直接建立二叉树再输出前序比较呀 = =反着想
1044动态数组范围求和,EZ第一次一遍过hh
1045顺序数列的最大值。想不清楚怎么做。感觉要贪心 【0724已经完成 dp动态规划】dp动态规划 思想很重要。
1046 case3超时 修改思路一边读取一边统计路径。减少遍历次数
1047基础题,优化一下就可以过最后一个用例了。
1048 调两个硬币付钱。 膜柳神+1;
1049数不大于N的正整数中1出现的个数。反复递归。(事实证明直接硬算都可以拿26分,考试的时候应该直接试一下复杂度是否超过)
1050 EZ.
1051 模拟栈,判断出栈顺序是否成立,没想象中的难哈~
1053 DFS
1052需要再做一遍的简单题!(最后一个测试点很坑)思路还是要严谨啊!
1054 只需要得到最大的数是什么的话,对对碰遍历一遍即可~ 很有启发性的巧题;
1055 基础排序题。
1056 用队列做了一遍,优先级队列好像不太好,然后题意一直都是读错的。T.T 输入的第三行数据是默认的程序猿0-N-1,然后根据这个数字选择第二排的mice
1057实现一个带有后进先出、输出排序下的中间值的堆,用了两个vector数组同步操作,一个后进先出、一个排序
```temp.erase(lower_bound(temp.begin(),temp.end(),last));//排序数组出数last=*(s.end()-1);```
```temp.insert(lower_bound(temp.begin(),temp.end(),num),num);//排序数组插入数```
```s.pop_back(); //正常数组出数```
```s.push_back(num);//正常数组进数```
```printf("%d\n",*(temp.begin()+(size+1)/2-1));//输出中间值```
1058EZ.
1059EZ.
1060浮点数的科学计数法,我觉得上次没能ac的原因是 因为数据大,所以是字符串输入,开头可以是0…(比如00012)
1061 读题
1062 EZ 常规排序题
1063 比较两组数据中重复的个数占比,第一次用set
,自动排序去重
很方便。
1065大数据加减…一共三个用例,全是0?????
1066 标准AVL建树题,再练!
1067 只用swap(0,i)排序。时间复杂度过不去,调试优化一小时。哭了
1068 找硬币升级版,受八皇后启发写的递归,不完美退出各种问题,拿了28分,感觉可以直接按顺序来。【0718更新】二次挑战dfs+剪枝还是最后一个点超时 29/30 看柳神说是01背包问题【0727更新】看了一下01背包,也是一种动态规划,抄了一遍代码还没完全弄懂,还要再做!
1069 EZ
1070EZ.
1071复习到MAP再做一遍 基础题但是有坑,特殊情况最后一个字符也是一个词。
1072dijkstra,调试半个小时最后发现是题目意思理解错了,满足条件的解里面最小距离里取最大的,一样大取平均距离最小的…蜜汁设定,然后根据柳神博客提醒,这种没说清楚有没有多条路的可能有脏数据,比如1-1距离为999,重复道路距离不一样…不过这道题并没有,目前也没碰到有脏数据的。所以这样看的话,邻接矩阵在输入的时候的筛选确实比邻接表方便多了,但是数据规模超过1000空间占用就得考虑了。
1073 EZ
1074 链表常规题,这种题注意有可能有不在链表里的,根据题目决定是否输出。
1075排序,坑多。读题
1076 图的BFS遍历,基础题~
1077 字符串末尾的公共子串,
reverse
函数在<algorithm>
里,reverse(str.begin(),str.end());
cin整行读取(包括空格)getline(cin,str);
1078 Quadratic probing (with positive increments only) 正向增加的二次方探查法
1079EZ.数组大小波动大时用vector
1080按顺序分配位置,排序逻辑基础题~25分钟一遍过很顺利。
1081分数加减法。注意结果为0的时候的特殊情况。
1082 拼音读数字。一共九位数所以穷举了。。要考虑的情况有点复杂。0、10000009、中间多个0有时候要合起来读0,有时候又不读。调试半天,还没想到聪明办法。
1083 考试有这么送分的题就好了。
1084 s1.find(s2[i])==string::npos
string::npos
表示找不到字符串。touppr
是include <cctype>
里的变成大写的函数。
1085 不难但是很可能会理解成题意。最小值不一定就是整个序列的最小,因为数字可能重复,在一个有序数列中找一串满足范围的最长子序列,用两个指示。
1086 根据前序和中序(出堆顺序)建树,输出后序。复习建树
1087 图的两点间所有路径遍历,下次再写一遍。22/30【0726已AC】最短路径计算前缀,dfs输出所有最短路径结果,再计算比较最优解。重新做一遍过。用时约45分钟。
1088 分数的加减乘除化简。注意化简:找最大公约数的函数gcd
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
1089按照步骤判断是合并排序还是插入排序,很有意思一题。
1090多叉树标记层次 空间换时间,建立vector哈希表
1091一直看不懂的题干原来就是一个三维bfs。设立三个坐标的标志位
1092EZ
1093感觉做过这题。。找字符串中PAT的个数,正向记录P的个数,反向记录T的个数,最后遇到A的时候,把两把的P\T个数相乘加到sum里就是了。
1094EZ.再做可以用树试试;
1095 STL 常规排序复杂模拟题,重写一遍过,用时约25分钟。
1096 求公因数里的最长连续串,题意理解不要错了,这个串乘起来不能比原来的数大 = =
1097 EZ 链表地址题目,似乎都不用真的建立链表结构2333
1098 蜜汁段错误,23/25 堆排序和插入排序比较 其实好像不需要模拟出来,各种排序都是有特点的。。比如插入排序前面就是排好的,后面是原顺序。堆排序后面是排好的。
堆排序 向下调整:
void downadjust(int b[],int s,int e){ int i=1,j=i*2; while(j<=e){ if(j+1<=e&&b[j]<b[j+1]) j++; if(b[i]>=b[j]) break; swap(b[i],b[j]); i=j;j=i*2; } }
1099给定BST树的结构,以及所用数据,输出层次遍历。开始真的写节点建树,然后两个测试点蜜汁段错误。实际上这种固定的题可以建立静态树,写起来还简单快些。
1100 EZ
1101判断是否为快排标准数(左边的数小,右边的数都大)每次遍历计算左边的数和右边的数太费时间了,空间换时间,新建数组计算从左数的最大值和从右数的最小值。思想很重要。坑点:必须输出2行,0个结果也要多换行输出一行空。
1102 二叉树的构建、中序层次遍历等;二叉树根据节点信息的构建;还要强化呀 二叉树
1103 DFS 有点不好想,一定要再独立写一遍理解加深。
1104 很简单的题,但是提醒了一个问题sum+=temp*i*(n+1-i);(0<temp<1)
不能写成sum+=*i*(n+1-i)*temp;
i*(n+1-i)
有可能溢出。。。
1105建立“回”型二维数组,海星。
1106 DFS同时记录最深节点个数。好好学下别人的代码。。自己写的太多无用项了。
1107 应该还是一个并查集的题,但是不熟练有点理不出清该用什么设置父元素,所以还是用vector做的,数据规模不大。vector的清理内存:vector<int>().swap(q[]);
1108 新的处理字符串的函数:【拓展学习】
scanf("%s",a); sscanf(a,"%lf",&temp); sprintf(b,"%.2f",temp);
1109 多重排序+找规律,时间复杂度优化。
1110判断是否为完全二叉树
完全二叉树需要满足:
1)如果一个结点有右孩子而没有左孩子,那么这棵树一定不是完全二叉树。
2)如果一个结点有左孩子,而没有右孩子,那么层序遍历里这个结点之后的所有结点都是叶子结点这棵树才是完全二叉树。
3)如果一个结点是叶子结点,那么层序遍历里这个结点之后的所有结点都必须是叶子结点这棵树才是完全二叉树。
调试半天错在输入的数可能是两位数,不能用char字符。汗
1111 两部分计算最短路径和最快路径,两次dijkstra,两次dfs遍历前驱节点。注意下最优解的比较条件。
1112 简单题但是感觉写的不精炼
1113 EZ
1114 家族树统计,可以理解为图,BFS遍历,结果保存到结构体里排序。
1115 建立二叉搜索树,map当作映射效率似乎有点低。复习二叉搜索树的建立和dfs遍历的写法。自己用节点位置映射写只得了27分,三个一分点没过。
1116 EZ
1117 EZ 注意0即可。
1118 复习到并查集再做一遍。遇到的问题:vector的空间只会增大不会缩小,erase/clear了以后所占的空间大小还是不变,导致这题有一个测试点出现了内存超限的情况。使用swap方法把这个vector销毁重新生成,可以释放占用的内存。vector<int>().swap(a);
a为需要释放的vector(swap到新定义的里面。)【重做】并查集的方法AC(真香啊)
1119 前序后序建树并确定是否唯一。很有意思的题目!后序的左右根,倒数第二个数就可以认为是右子树的根。在前序中查找这个树来划分。
1120简单题 读清楚题意,例子肯定不会错的。。
1121 EZ
1122 图遍历检测,EZ
1123 平衡二叉树AVL的建立,学习左旋、右旋、以及两次旋转的调整。insert函数的写法(根据左右子树的深度判断是否要调整,根据插入值和两级父节点的大小比较判断旋转的方向和次数) 要记忆要再写一遍!难题 还有就是层次遍历的时候如何设计标志位置判断是否为完全二叉树(当某一层没有左右子树(为NULL)时,激活标识after,然后如果后面还有继续下一层的push进队的动作,就说明不是完全二叉树了)
1124 EZ
1125 题意:单词halved减半。从最小到最大,依次合并插入,使用可重复的有序容器multiset。
1126 一笔画?注意图如果不连通的情况,一个测试点5分,所以需要dfs一边。
1127 间隔倒序层次遍历。
1128 判断N皇后是否成立,注意不成立要把剩下的数读完。
1129 一遍读取一遍排序输出当前排序结果。使用set可以自动排序,但是多个元素构成的结构体放进set里 需要重载运算符
struct info{
int qnum;
int time;
bool operator <(const info &a) const{
return (time!=a.time)?time>a.time:qnum<a.qnum;
}
};
1130 表达式的中缀输出。还要加括号。DFS 分析:首先根据所有孩子结点编号寻找1~n中没有出现过的编号标记为root,即树的根结点~然后进行从root结点开始dfs~dfs递归拼接 “(” + 左子树 + 根 + 右子树 + “)”
递归有四种情况(有效的只有三种):
1. 左右子树都空 返回 “(” + 根 + “)”
2. 左空右不空 返回 “(” + 根 + 右子树 + “)”
3. 左不空右空 这种情况不存在
4. 左右都不空 返回 “(” + 左子树 + 根 + 右子树 + “)”
最后递归返回的ans,最外层可能会被括号包起来,也可能不被包起来。要判断一下,如果被包起来,把最外层括号去掉
1131 地铁题,dij最后一个点超时,也不好写,是不是所有图最短路径的题都可以直接dfs搜一切。。
1132 被除数为0的时候取余也会引发浮点错误。
1133 链表数据常规题,好像这种题都不需要建立动态链表。。有机会还是试试都用动态链表做。
1134 常规做法。题目理解了就好做。单词:vertex:(三角形或锥形的) 角顶; 顶点; 至高点;
1135判断是否是红黑树,注意红黑树不是AVL,并不平衡,一开始用静态链表写,想用坐标,结果后面两个测试点段错误,很明显是一直*2数组越界。所以还得乖乖建树。这题全是递归思想 代码很值得思考。
1136 回文数判断+字符串数字相加。题目并没有说清楚如果A就是回文数不需要计算直接输出。
1137 简单,注意向上取整的方法可以直接(int)(expression+0.5)
1138 前序+中序输出后序,题目只要后序的第一个。所以树都不用建立。。直接遍历【膜柳神tql。而且建树的时候前序的右端点也是无用变量?
1139 坑点:找的朋友不能是自己和目标,其次0000和-0000都会被int读为0,无法区分性别。输出%04d
1140 数字符串 EZ
1141 基础STL 注意一个把字符串整体转换大小写的方法:transform(temp.begin(),temp.end(),temp.begin(),::tolower);
1142 和1134有点像,理解题目就好做了。单词:adjacent 相邻的
1143 根据前序遍历找BST中两个节点的最低公共父节点。复习了一遍建树然后写了个find同时查找两个,然后就超时了两个点,也没法优化了,看了柳神的思路发现并不需要建树:前序遍历就说明了,从头到尾,后面的点层次肯定小于等于前面的点的,要满足公共祖先的话就是第一个处在所求a,b两数中间的数。
1144超大数组定义在全局。#define MAX 2147483647
1145 又是一题正向平方探测法的哈希表。注意查找的时候,如果查到某个位置为0(没值)直接就说明这个数字不存在了,因为这就是如果它存在,会在的位置。题目测试数据很巧妙,没注意到这一点是一样的结果,然后就只有1分。难顶。
1146 检查是不是拓扑排序的序列,拓扑排序好像是考纲要求,没见过真的考这个的题。
1147 判断是否为大顶堆、小顶堆,输出后序。注意判断的界限<=n/2前一半(没有子节点)
1148 awsl…学不会这逆向思路,两层循环,假设i,j是狼,用一个+1,-1数组标记每个人的好坏属性,除了i,j是-1都是+1;然后按顺序,每个人说话的声明如果和这个好坏属性冲突(<0),那么这个人就撒谎了。if(state[k]*a[abs(state[k])]<0) lie.push_back(k);
最后判断撒谎的人数是不是两个人,是不是一个好一个坏。
1149 EZ 读懂即可 似乎也没简单方法…
1150 常规题读懂即可。用一个vis数组记录经过次数,分类讨论。
1151 不需要建树 找规律,前序和中序顺序中,按照中序右到左,存在于前序左边点之前的,就是答案。
1152找出序列中的第一个prime数,注意(0,1不是素数)注意输出前面的0,所以干脆直接输出取出来的字符串。字符串转数字好像有个stoi
函数,不过自己写一个也很快。
1153 非常非常细节的基础题:1.输出各种%03d,%06d
2.同样类型的查询,前面用过的计数数组要清空(type==3) 3. 0个结果输出NA 4. 输出格式的空格。
1154 EZ 读懂题,注意序号开始的是0还是1;
1155 EZ…30分的题就是判断一个完全二叉树是不是大小顶堆,遍历输出每一个路径。