【PAT刷题甲级】部分笔记1001-1064~(上)

写在前面

这里C++菜鸟一枚~
暑假将近两个月刷PAT甲级的笔记在此,虽然最终也没有取得满意的结果,但是不可否认,还是从中学到了很多,是我准备的还不够充分,希望能给刷题的同学们一些帮助。
PS:不是每道题都有,仅仅记录了本人刷过的题中记下的一点心得,分为上下两篇笔记。
下篇:【PAT刷题甲级】部分笔记1065-1155~(下)

常用知识点:

1. 数据类型转换
(1) string 类型转 int 、 long 、 long long 、 float 、 double 、 long double
// 头文件 #include < string > :
stoi 、 stol 、 stoll 、 stof 、 stod 、 stold

(2) char c[10] 类型转 int 、 long 、 long long
// 头文件 #include < cstdlib > :
atoi 、 atol 、 atoll

(3) int 、 long 、 long long 、 float 、 double 、 long double 转 string
// 头文件 #include < string > :
to_string

2.随机数

#include < cstdlib >
#include < ctime >
srand((unsigned)time(NULL)); //生成随机种子
再使用rand()函数即可
输出给定范围内的随机数需要使用rand()%(b-a+1)+a //[a,b]范围内的随机数
输出一个大范围内的随机数

(int)((double)rand()/32767*(b-a+1)+a)
(int)(round(1.0*rand()/32767*50000+10000))
//[10000,60000]内的随机数

1001:将数字显示成英语中常用格式,每三位用逗号分离(简单模拟)

commas 逗号
关于字符串中insert函数:

string str="hello";
string s1="Hahah";
str.insert(1,s1);
//在字符串s下标为1的字符前插入字符串s1(字符串下标从0开始)
str.insert(4,5,c);
//在字符串s下标为4的字符o前插入5个字符c
str.insert(0,s1,1,3);
//将字符串s1从下标为1的e开始数3个字符插入字符串s的下标为0的字符前

1002:多项式相加(简单模拟)

polynomial 多项式
exponents 指数 coefficients 系数
nonzero terms 非零项
使用标记数组,用数组自然的序号来表示指数,对应值表示系数
c[i]=j表示指数i的系数为j

1003:最短路径问题(Dijkstra算法)

fill函数可以为数组或者vector中的每个元素赋以相同的值,通常用于初始化!
数组的效率往往比vector高,使用assign函数只能对vector赋初值~所以当要对数组赋初值时可以使用fill函数。
输入:

//fill函数包含在<algorithm>中
eg:	int v[10];
	fill(v,v+10,-1);

输出:

-1 -1 -1 -1 -1 -1 -1 -1 -1 -1

输入:

int v[10][10];
fill(v[0],v[0]+10*10,-1);

输出:

-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1

1004:数叶子(DFS)

pedigree 家谱;起源;纯种的
a two-digit number 两位数
The input ends with N being 0. That case must NOT be processed.
输入以n为零。不得处理该情况。
输出每一层的孩子数

vector< int > v[100] 和 vector< int > v(100)
vector初始化后所有元素都是0/false/空。v[100]是二维数组,v(100)是一维
vector< int > v[100]是创建一个有100个vector的vector数组(每个vector的size为0),vector< int > v(100)是创建一个vector,其容量为100

1005:输入一串数字求和,并用英文表示(字符串处理)

法一:

#include <iostream>
using namespace std;
    char n[101];
    cin >> n;
    int sum=0,i=0;
    while(n[i]!='\0'){
        sum+=n[i]-'0';   //字符转为数字求和
        i++;
    }

法二:

char c;
int sum=0;
while((c=getchar())!='\n')  //getchar()函数是从I/O字符流中读取一个字符,必须输入换行才能读入字符。
    sum += c-'0';  //字符转为数字求和

1006:记录最早签入、最晚签出(简单模拟)

比较时间:start = 3600 * h1 + 60 * m1 + s1;
end = 3600 * h2 + 60 * m2 + s2;

1008:电梯(简单模拟)

注意审题!第一个数是总共要输的序列数,后面依次输入序列元素
positive numbers 正整数
事先不知道要输多少,夹杂空格输入数字,遇换行停止输入

vector<int> v(0); //动态数组
int n;
while (cin >> n) {
	v.push_back(n);
	if(cin.get() == '\n')	break;
}
int len = v.size();

1009:多项式乘法(简单模拟)

1011:世界杯投注(简单模拟)

1012:最佳排名(排序)

输入每位学生的ID号及各科成绩,平均成绩需要自己算
输出每位学生的最佳排名(单科或平均),若两位同学排名一样,按A>C>M>E的优先级排序

//sort函数头文件:#include <algorithm>
struct node { 				//定义结构体stu
	int id,best;			//学号
	int score[4],rank[4];	//三科成绩+平均成绩以及相应排名(平均分需要四舍五入)
} stu[2001];

bool cmp(node a, node b) {
	return a.score[flag] > b.score[flag];	//用于计算各科成绩的排名
}

sort(stu,stu+n,cmp);

1013:保卫城市(图的遍历,DFS,统计强连通分量的个数)

用DFS遍历图,可以统计强联通分量个数n,若想要分立的连通分量变为连通图最少需要n-1条线!

1015:可逆素数

一个数本身是素数,且在转换成D进制数后反转后再转换为十进制后也是素数
即:1.先判断该数是否为素数
2.将该数转换为D进制
3.将转换后的数逆转,再转换为十进制,判断是否为素数
4.两次判断均为素数才可输出Yes,否则输出No
a negative N 负数N
radix 基数
radix D D进制

(1)sqrt:

#include <cmath> 
//sqrt只支持double和float类型,使用时需要强制类型转化
//可以这样
c=(int) sqrt((double)a*a+b*b);
//或者
c=(int) sqrt((float)a*a+b*b);

(2)判断素数

bool isprime(int num) {	//判断素数
	if(num<=1) return false;
	int sqr=(int) sqrt(1.0*num);
	for(int i=2; i<=sqr; i++) {
		if(num % i ==0)	return false;
	}
	return true;
}

(3)将十进制 a 转换为 b 进制数,当 a 不等于 0 时,将 a%b 从后往前倒序保存下来,每次保存后将 a/b 。这样倒序保存的数就是十进制 a 在 b 进制下的结果。

int DtoN(int num,int d) {	//十进制数转换为N进制
	int dnum=0,i=0,count=0;
	while(num!=0) {
		n0[i] = num % d;
		num = num/d;
		i++,count++;
		dnum += n0[i] * pow(10,count-1);
	}
}

(4)关于while(scanf("%d",&n) != EOF)

while(scanf("%d",&n) != EOF){ 
	
}
	return 0;
}

当上面的程序运行时,如果不加" != EOF",那么这个程序就是个死循环,会一直运行下去;加上" != EOF"后该程序就不是死循环了,如果在终端不进行输入该程序会自动结束(while的意思就是说当当前输入缓存还有东西时就一直读取,直到输入缓存中的内容为空时停止)。
在这"scanf("%d",&n) != EOF"相当于"scanf("%d",&n) != EOF",或"~scanf("%d",&n)",或"scanf("%d",&n) == 1 " 。scanf的返回值由后面的参数决定。

但是在C++中不存在这种用法,但相同作用的有while((cin >> a) != 0)

1018:共享单车管理(最短路径+DFS)

vertice 点
edge 边
边权代表时间,点权表示存储的单车数。假设每点单车最大储量为10
vector中的函数clear()删除储存在vector中的所有元素.

Dijkstra求最短路径,dfs求minNeed和minBack和path,dfs的时候模拟一遍需要调整的过程,求出最后得到的need和back,与minNeed和minBack比较然后根据情况更新path,最后输出minNeed path 和 minBack,记得path是从最后一个结点一直到第一个结点的,所以要倒着输出~
vector删除元素pop_back(),默认删除最后一个元素

1019:回文数字

Palindromic Number 回文数字
decimal number 十进制数

1020:树的遍历

postorder traversal 后序遍历
inorder traversal 中序遍历
给出后序遍历和中序遍历,输出层次遍历
可以使用map,key标记改点的下标,最后按照key依次输出

void pre(int root, int start, int end,int index) {	//根据后序和中序输出先序 
	if(start > end) return ;
	int i = start;
	while(i < end && in[i] != post[root]) i++;
	level[index]=post[root];	//用index保存每次的根结点 
	pre(root-(end-i)-1,start, i-1,2*index+1);
	pre(root-1,i+1,end,2*index+2);
}
// ⽤迭代器遍历,输出map中所有的元素,键⽤it->first获取,值⽤it->second获取
for (auto it = m.begin(); it != m.end(); it++) {
cout << it->first << " " << it->second << endl;
}
// 访问map的第⼀个元素,输出它的键和值
cout << m.begin()->first << " " << m.begin()->second << endl;
// 访问map的最后⼀个元素,输出它的键和值
cout << m.rbegin()->first << " " << m.rbegin()->second << endl;
// 输出map的元素个数
cout << m.size() << endl;
return 0;

1021:最深根(DFS)

图是联通的且无环可视为树。
输出能使树的高度最大的根,有多个按升序输出,若不能生成树,输出该图的连通分量个数。
acyclic 无环的
adjacent 毗邻的

首先进行DFS计算连通分量个数,>=2不能形成树,=1可以形成树。然后进行两次DFS,第一次先从一个结点遍历保存最高高度层的叶子节点,然后在这些叶子节点中随机选一个进行第二次DFS,同样得到最高高度层的叶子节点,两次叶子节点集合的并集即为所有的最深根。

1022:数字图书馆(map的使用)

(1)getline函数可以输入带空格的字符串getline(cin, inputLine);,读到换行符就结束
如果cin和getline同时使用需要在cin>>后加上 cin.ignore();或者直接用scanf

cin.get (char *str, int maxnum)
cin.get()函数可以接收空格,遇回车结束输入。

cin.getline (char *str, int maxnum)(包含头文件#include )
cin.getline()函数可以同cin.get()函数类似,也可接收空格,遇回车结束输入。
在cin与cin.getline()之间加上cin.get();语句
fflush(stdin); //刷新缓冲区

(2)map中的find函数和count函数:
①find()
在map中查找关键字(key) 为 k 的元素,返回指向它的迭代器。若k不存在,返回 map::end.
返回值是一个迭代器,成功返回迭代器指向要查找的元素,失败返回的迭代器指向end

②count()
统计map中关键字(key)为 k 的元素的个数,对于 map,返回值不是 1 (存在),就是 0 (不存在)
返回值是一个整数,1 表示有这个元素,0 表示没有这个元素。只会返回这两个数中的 1 个。可以用于判断某值是否存在

1023:趣味数字(大整数的乘法)

duplication 重复
permutation 排列
一个9位数,每个数字不重复,两倍后仍然满足此要求。
输入一个k位数,双倍后仍然不重复,只是重新排列。

1024:回文数Palindromic Number

所有的一位数都是回文数
字符串赋值用#include < cstring > 下 strcpy(a,b); //把字符串b复制给字符串a

1025:PAT排序(排序)

1027:火星上的颜色(进制转换)

1028:列表排序(结构体排序)

1029:中位数(数字处理)

1030:旅游计划(Dijkstra+DFS)

记住模板!

1031:U字形输出字符串(图形输出)

1032:共享(链表)

可用flag标记在第一个链表中出现的字母,后面遍历只需要flag==true就可输出两个链表公共部分的起始位置。

1034:犯罪团伙的头(图的遍历DFS)

threshold 阈值,下限,临界值

1035:密码(字符串)

两字符串比较用strcmp,两单字符比较直接用==

1036:男孩女孩(简单模拟)

1037:获得钱的最大值(贪心)

排序,之后负的与负的相乘,正的与正的相乘即可,用两个while循环。

1038:恢复最小数(贪心)

对于不同长度字符串的拼接,组装成一个一个最小数。
用cmp函数!

bool cmp(string a,string b){
	return a+b < b+a;
}

1039:学生的课程表(map、set的使用)

根据输入信息输出每个学生的选课情况

1041:最独特(散列)

对10000以内的数字列表,统计每个数字出现次数。

1042:洗牌器(简单模拟)

Spade 黑桃
Heart 红心
Club 梅花
Diamond 方块
Joker 鬼牌
permutation 交换,排列

char c[6]={"SHCDJ"};
for(int i=1;i<55;i++){
	trans[i]=trans[i]-1;
	printf("%c%d",c[trans[i]/13],(trans[i]+1)%13);
	if(i!=54) printf(" ");
} 

1043:它是二叉排序树吗?(BST)

根据先序和中序输出后序遍历

1044:火星购物(二分查找)

int binfind(int i,int &j,int &tmp) {	//二分查找,每次固定i-1点,遍历之后的点来查找>=m的值 
	int left = i,right = n;
	while(left < right) {
		int mid = (left + right) / 2;
		if(sum[mid]-sum[i-1]>=m) {
			right = mid;
		} else {
			left = mid + 1;
		}
	}
	j = right;
	tmp = sum[j] - sum[i-1];
}

1046:最短距离(简单模拟)

环形路,输出两点之间最短距离,每次计算距离和,最终只要计算两点之间的距离差即可,无需再次相加,否则会超时。
两点之间每次都有两条路径,顺时针或者逆时针,取两者间较小者输出即可。

1047:课程的学生名单(vector的使用)

for(auto it=v[i].begin(); it!=v[i].end(); it++) {
	printf("%s\n", it->c_str());
}

1048:找硬币(标记数组)

因为总额不会超过1000,故可定义数组标记1000以内的数出现的次数。只要遍历该数组即可。

1050:字符串分割(散列)

使用bool marked[256]标记需要删除的字符即可。
输入带空格的字符串,遇空格停止输入
string s;
getline(cin,s);

1051:弹出序列(栈模拟)

原思路(18/25):

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
int main() {
	int m,n,k;
	scanf("%d%d%d",&m,&n,&k);
	for(int i=0; i<k; i++) {
		vector<int> v(n);
		for(int j=0; j<n; j++) {
			scanf("%d",&v[j]);
		}
		if(v[0]>m) {
			printf("NO\n");
			continue;
		} else {
			int flag=1;
			for(int j=1; j<n; j++) {
				int det=v[j]-v[j-1];
				if(abs(det)>1) {
					sort(v.begin(),v.begin()+j);
					int a=v[0]-v[j];
					int b=v[j]-v[j-1];
					if(det<0) {
						if(a>1) {
							flag=0;
							printf("NO\n");
							break;
						}
					} else {
						if(b>1) {
							flag=0;
							printf("NO\n");
							break;
						}
					}
				} else if(det==0) {
					flag=0;
					printf("NO\n");
				}
			}
			if(flag==1)	printf("YES\n");
		}
	}
	return 0;
}

1052:链表排序

1053:相等权值的路径(用DFS进行树的遍历)

给出一个值,找出总权值等于该值的所有路径

1054:主色(map的使用)

pixel 像素

1055:世界上最富有的人(结构体排序)

1056:老鼠和米饭(队列)

permutation 排列
注意思路!

1057:栈(分块)

模拟,但要使用分块思想找第k小的数,用sort会超时。

1058:哈利波特里的A+B

long int输入输出为 %ld

1059:素数因子(素数)

给出一串long int型数字,将其拆成素数指数幂之积的形式,若指数为1不用输出。

for(auto it=p.begin(); it!=p.end();) {
	printf("%ld",it->first);
	if(it->second!=1)	printf("^%ld",it->second);
	if(++it!=p.end())	printf("*");
}

最后一个数与之前的不同,采用++it!=p.end()表示。

1060:他们相等吗(数字处理)

Note: Simple chopping is assumed without rounding.
注意:假设没有四舍五入的简单截取。
significant digits

1061:约会(字符串处理,直接用普通for循环,无需用迭代器)

capital English letter 大写英文字母
case sensitive 区分大小写
两个字符串,第一个共同的大写字母是D,代表周四;
第二个共同的大写字母是E,代表14:00(09和AN代表0~23点)
最后两个字符串共同的字母是s且都在第4个位置,代表第4分钟
给出两对字符串,计算约会时间。(DAY HH:MM 周几用三个字母简写表示)

1062:天赋和美德(结构体排序)

记住cmp每个都要return返回结果!

1063:集合的相似度(map、set的使用)

1064:完全二叉排序树(中序遍历)

由于BST的中序遍历恰好为升序排列,用level记住他们的位置即可得到层序遍历。
根的左节点为2root+1,右节点为2root+2

inorder(2*root+1);
level[root]=in[t++];
inorder(2*root+2);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值