【PAT刷题甲级】部分笔记1065-1155~(下)

写在前面

接上篇【PAT刷题甲级】部分笔记1001-1064~(上)
这里是1065-1155,同样仅为本人刷的题部分笔记,不包括所有题,希望对刷题的同学有帮助~
上篇:【PAT刷题甲级】部分笔记1001-1064~(上)

1065:A+B和C(64进制)(大整数运算与比较)

cin和scanf还真有点不同,如果读取的数溢出,cin得到的是最大值,而scanf得到的是溢出后的值

struct bign {	//大整数
	int d[22];
	int len;
	bign(){
		memset(d,0,sizeof(d));
		len=0;
	}
};

bign change(char str[]) {			//字符串转为大整数
	bign a;
	if(str[0]!='-') {
		a.len = strlen(str);
		for(int i=0; i<a.len; i++) {
			a.d[i]=str[a.len-i-1]-'0';	//逆序赋值
		}
	} else {
		a.len = strlen(str)-1;
		for(int i=0; i<a.len; i++) {
			a.d[i]=str[a.len-i]-'0';	//逆序赋值
		}
	}
	return a;
}

bign add(bign a,bign b) {	//大整数相加
	bign sum;
	int carry=0;	//进位
	for(int i=0; i<a.len || i<b.len; i++) {
		int temp = a.d[i] + b.d[i] + carry;
		sum.d[sum.len++] = temp % 10;	//个位留下做和
		carry =  temp / 10;				//十位作为进位
	}
	if(carry!=0) {	//最后一位进位不为0,直接加到最高位上
		sum.d[sum.len++] = carry;
	}
	return sum;
}

bign sub(bign a,bign b) {	//大整数相减
	bign c;
	for(int i=0; i<a.len || i<b.len; i++) {
		if(a.d[i]<b.d[i]) {
			a.d[i+1]--;
			a.d[i] += 10;
		}
		c.d[c.len++] = a.d[i] - b.d[i];
	}
	while(c.len-1>=1 && c.d[c.len-1]==0) {
		c.len--;		//去除高位的0,保留至少一位
	}
	return c;
}

int compare(bign a,bign b) { 	//大整数的比较,a大,相等,a小分别返回1、0、-1
	if(a.len>b.len)	return 1;
	else if(a.len<b.len)	return -1;
	else {
		for(int i=a.len-1; i>=0; i--) {	//从高位向低位比较
			if(a.d[i] > b.d[i]) return 1;
			else if(a.d[i] < b.d[i])	return -1;
		}
		return 0;
	}
}

void print(bign a){
	for(int i=a.len-1;i>=0;i--){
		printf("%d",a.d[i]);
	}
}

1066:AVL树的根(AVL)

AVL的相关模板记牢!

1067:用交换排序(贪心)

permutation n.置换;排列(方式);组合(方式)
看清题意,要求只能用0与其他数字交换!
输入N,给出0—N-1的乱序版,要求只能将数字0与其他数字交换来获得递增序列。
首先找到0所在位置,将0与其位置本来应该在的元素进行交换,这样可以通过0将一些元素交换至正确位置。
如果0回到位置0,但是还是有其他数字乱序,那么将0与之后的不在正确位置上的数字交换,再次进行以上操作,直至所有的数字都在正确位置上。

1069:数字的黑洞(数字处理)

第一次非递增排列,第二次非递减排列

1070:月饼(贪心)

1071:演讲模式(字符串处理)

输入一行字符串,以换行符做结束符。至少包含一个字母或数字组成的字符串。
输出使用最多的字符串(区分大小写)
lexicographically smallest 字典序最小
输入带空格的字符串,以换行符做结束符:
string s;
getline(cin,s);

1072:加油站(Dijkstra+DFS)

1073:科学记数法(数字处理)

输入科学记数法,输出普通记数法
科学记数法的长度不超过9999
指数的绝对值不会超过9999

1074:倒置链表

1075:PAT评分(结构体排序)

未提交该题得分状态为’-’。
注意:只有全部题目都未提交或者提交的都未通过编译,才不能参与排名

1076:微博转发(BFS)

求最多转发次数,粉丝可看到自己关注的人发的帖子并转发,不可转发自己的帖子
只计算符合间接追随者的级别数的人转发数,即有L次的转发限制
vector<vector> 二维数组:存放i的粉丝id
给出每个用户关注的人的id,和转发最多的层数,求一个id发了条微博最多会有多少个人转发

1077:Kuchiguse(最长公共后缀)

case sensitive 区分大小写
输出最长的共同后缀
(1) #include < algorithm > reverse(s.begin(),s.end());
(2) 字符串可直接等于其子串,eg: s=s.substr(2,1);
(3) getline之前使用cin要加getchar(); 或者cin.ignore();
或者使用scanf("%d\n",&n);

1079:供应链的完整销售(广义树)

理解题意,抽象为一棵树。
注意:不超过10^10应该用double型
层序遍历即可

1080:研究生录取(结构体排序)

1081:分数的加减

numerator/denominator 分子/分母

long int gcd(long int a,long int b) {	//最大公倍数 
	if(b==0)	return a;
	else	return gcd(b,a%b);
}

假设a,b的最大公倍数是d,则a,b的最小公约数是a/d*b

1083:列表成绩(简单排序)

1084:坏键(散列)

case insensitive 不区分大小写
capitalized 大写

1085:完美数列(双指针)

int res=0,len=0;
for(int i=0; i<n; i++) {
    for(int j=i+res; j<n; j++) {
        if(v[j]<=v[i]*p) {
	 		len = j-i+1;
	 		if(len>res) {
	     		res = len;
	 		} else 
	     		break;
		}
    }
}

1086:树的再次遍历(树的遍历)

先序遍历 非递归 用栈
(1)根据先序序列和中序序列输出后序序列:

vector<int> pre,in,post;
int n;	//结点总数
void topost(int is,int ie,int ps,int pe) {	//中序起始位置,中序结束位置,先序起始位置,先序结束位置
	post[--n]=pre[ps];						//倒着存,应该是根右左的顺序
	int i=0;
	while(i<ie && in[i]!=pre[ps])	i++;
	if(ie-i>0)	topost(i+1,ie,i-is+1+ps,pe);	//如果存在右子树,先存右节点
	if(i-is>0)	topost(is,i-1,ps+1,i-is+ps);	//如果存在左子树,存左节点
}

(2)根据后序和中序输出先序 :

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);
}

1087:条条大路通罗马(Dijkstra)

1088:分数的运算

parenthesis 括号
分数的加、减、乘、除
rational numbers 有理数
sum, difference, product and quotient 和、差、积、商
numerator 分子
denominator 分母
化简可以专门写一个函数来进行多次应用,两个long int型相乘可能会超出long long型,故在判断a、b异号时,不可用a*b < 0来判断,只能用flag标记两种异号情况来表示。

1089:插入排序或归并排序

1090:供应链中的最高价格(广义树)

与1079题相似

1091:急性脑卒中(三维数组的BFS)

pixel 像素
threshold 阈值
volume 容量,音量,体积
队列中保存的只是原元素的一个副本

1092:买或者不买(散列)

1093:数PAT的子串

最终结果对1000000007取模
柳神思路:计算PAT的个数,只要遍历字符串中的每个A,A前面的P和后面的T的乘积就是PAT的个数。

1094:最大后代(广义树的层序遍历)

1095:校园里的汽车(比较复杂的模拟,排序,重点是思路)

plate_number 车牌号

1096:连续因子(因数分解)

连乘思想,构造连乘,看其是否为n的因数,若是再判断是否比之前的长度长。
初始长度一定为0

#include <cmath>
maxx = (int) sqrt(1.0*n)+1
//注意i=2;i<=maxx;i++

1097:链表数据去重(链表)

deduplication 重复数据删除,数据去重
去除相同或绝对值相同的多余数字
将去除多余数字的链表和多余数字组成的链表均输出

1098:插入排序或者堆排序

(1)插入排序特点:每次将未排序的插入已排序序列中正确位置。
因此插入排序前面一部分有序,后面一部分乱序(与未排序前一致)
(2)堆排序特点:后面总是从小到大的,因此从后往前扫描遇到第一个比heap[1]小的元素,就与之交换,再向下调整。

1099:建立一棵二叉排序树(BST)

给出各个节点的孩子情况,输出该BST的层序遍历

1100:火星数字(进制转换)

地球语言和火星语言转换

1101:快速排序

作为主元,必须满足其左边的数都小于它,其右边的数都大于它
找有几个数可作为主元(哨兵)
给出一串序列,判断其中几个数可作为主元

1102:倒置一棵二叉树(二叉树的遍历)

输出倒置二叉树的层序遍历和中序遍历
先找根节点,没有父节点的就是根节点

1103:整数因子(DFS+剪枝)

n,k,p 整数,因子个数,指数
要求n=n[1]p+……+n[k]p
可先将从0开始到n的ip存入vector中,直到ip>n,这样之后再用直接加即可
DFS注意剪枝,只有psum+v[index]<=n才能继续DFS
nowk == k是大前提,若nowk==k,但是psum!=n时需要剪枝。

1104:计算顺序子序列之和(数学问题,注意精度)

double %lf
long double %Lf
long double和double的比较:
二者均为浮点数类型,区别如下:
(1) double类型为C++原始类型,所有编译器均支持,而long double是C99规范增加的新类型,只有支持C99的编译器才支持long double;
(2) 占用大小不同,double占8个字节,long double根据编译器实现不同,有占用8,10,12字节和16字节四种;
在long double用8字节实现时,long double 和double没有其它区别。对于其它实现方式,还有以下三项区别:
① 运算速度不同,long double占用字节多,运算速度会慢一些;
② 精度不同,long double可以表示更大的精度;
③ 表示范围不同,long double可以表示更大范围的浮点数。

1106:供应链的最低价(广义树)

同1079、1090相似

1107:社会集群(并查集)

1108:寻找平均数

break 终止整个循环,在多层循环中, 一个break语句只向外跳一层
continue 只终止本次循环,跳过剩下语句直接进行下一次循环
#include <stdio.h>
sscanf(str,"%d",&n); //将字符串str中%d的内容赋值给n
sprintf(str,"%d",n); //将n以“%d”形式写入字符串str中

1110:完全二叉树(CBT)

判断是不是完全二叉树

1111:线上地图(两次Dijkstra+DFS)

记牢Dijkstra+DFS模板
one-way 单向

1112:阻塞的键盘(字符串处理)

判断坏键,按1次可能出现k次,那么坏键的判断只有一次,不可能出现先不是坏键后来又是坏键的情况,也不可能出现先是坏键后来又不是坏键的情况。
只有出现cnt%k的时候可能是坏键,要保证该字符每次出现都会出现cnt%k才能保证是坏键。
字符一共256个,可以开标记数组标记每个键的好坏情况。已经确定s是好的。
将坏键都存放在set中。
给一段结果字符串,输出原来的字符串
字母可能重复k次(除了s)
确定坏键并输出,不能直接用map的原因是需要按照坏键发现的顺序输出,而map会自动排序

1113:整数集合划分(简单数学问题)

1114:家庭财产(并查集)

注意用两个结构体,一个用来接收数据,一个用来存放结果,
让每个家庭的最小id做根节点

1115:BST中数结点(层序遍历)

分别统计最底2层的结点数

1116:Come on! Let’s C (简单模拟)

根据排位榜输出要求查询ID所获奖项,已查询的输出Checked

1117:Eddington数字

骑手骑行有E天都超过E公里,求最大的E

#include<algorithm>//因为用了sort()函数
#include<functional>//因为用了greater<int>()
sort(a,a+len,greater<int>());//内置类型的由大到小排序

1118:森林中的鸟(并查集)

1120:朋友数(map)

1121:Damn Single(单身狗)(散列+vector)

记住要考虑那些原本就不在配对列表中的人。
若直接初始化int couple={-1}
只能初始化第一个为-1
全部初始化为-1可用fill:fill(couple,couple+100000,-1);

1125:连接绳子(贪心)

be rounded to the nearest integer that is no greater than the maximum length 向下取整
floor() 向下取整
ceil() 向上取整
round() 四舍五入
强制转换,直接截取

1127:树中的Zigzagging

先根据中序、后序建树

node* create(int ps,int pe,int is,int ie) {	//后序、中序确定一棵二叉树
	if(ps>pe)	return NULL;
	node* root=new node;
	root->data = post[pe];
	int k;
	for(k=is; k<=ie; k++) {
		if(in[k]==post[pe]) {
			break;
		}
	}
	int numleft=k-is;	//左子树个数
	//返回左子树的根结点地址,赋值给root的左指针
	root->left=create(ps,ps+numleft-1,is,k-1);
	//返回右子树的根结点地址,赋值给root的右指针
	root->right=create(ps+numleft,pe-1,k+1,ie);
	return root;	//返回根节点地址
}

再层序遍历,用v[31]保存每层结点的数值,再按照Z字形输出即可。

1129:推荐系统(结构体排序)

需要用到结构体内部’<'重载

node(int a, int b):id(a), cnt(b) {}			//方便插入和删除node 
struct node {
	int id,cnt;
	node(int a, int b):id(a), cnt(b) {}			//方便插入和删除node 
	bool operator < (const node &a) const {		//结构体内部"<"重载 
		if(cnt != a.cnt)	return cnt > a.cnt;
		else	return id < a.id;
	}
};

1130:表达式(二叉树的中序遍历)

注意加括号问题:
只有右子树不为空且不是根节点时需要加括号。

1132:整数切分(简单模拟)

1133:按要求排序(链表)

vector的合并:

res.insert(res.end(),res2.begin(),res2.end());  //合并vector数组
res.insert(res.end(),res3.begin(),res3.end());

1134:点的覆盖(简单模拟)

注意使用map代替三重循环,以免超时
incident to 易发生于

1135:它是红黑树吗

红黑树的性质:
(1)结点是红色或者黑色
(2)根结点总是黑色的
(3)叶结点总是黑色的(红黑树的叶子节点不是没有子节点的节点,而是为null的结点)
(4)每个红色结点的两个子结点都是黑色的
(5)从任意结点到每个叶结点的所有路径都包含相同数量的黑色结点

1136:延迟的回文数(大整数相加+判断是否为回文数)

1137:最终成绩(排序)

1138:后序遍历

根据先序和中序输出后序的第一个数字。

void topost(int ps,int pe,int is,int ie) {
	if(ps>pe)	return;
	int k;
	for(k=is; k<=ie; k++) {
		if(in[k]==pre[ps])
			break;
	}
	int numleft=k-is;
	post[--n]=pre[ps];
	topost(ps+numleft+1,pe,k+1,ie);
	topost(ps+1,ps+numleft,is,k-1);
}

1140:看并说序列(字符串处理)

后一个数一描述前一个数的,将前一个数分为不同的统计规格数并在下一个数输出

1141:学院的PAT排名

分数相同,根据人数递增排序,人数相同,按学院名字典序排序

1143:最低的共同祖先(LCA)

BST树,对其先序遍历,从a开始,若a在u,v之间,或者a=u或者a=v则a就是u和v的最低共同祖先。

1144:丢失的数字(map)

使用map!
然后while(++j){
if(m[j]==0) break;
}
cout << j;

1147:堆

判断是否为堆(包括大根堆、小根堆)

int minn = 1, maxn = 1;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 2; i <= n; i++) {
    if (a[i] > a[i / 2]) maxn = 0;
    if (a[i] < a[i / 2]) minn = 0;
}
if (maxn == 1) printf("Max Heap\n");
else if (minn == 1) printf("Min Heap\n");
else printf("Not Heap\n");

1148:狼人杀简单版本(思路!!)

in ascending order 以递增顺序

1149:危险货物打包(map+散列)

flag等到全部判断完后在讨论=0或者=1的问题

1151:二叉树中的共同祖先(LCA)

这是普通二叉树,不是BST

1152:谷歌招聘(素数)

记住i<=l-k

1153:解码PAT注册卡(结构体排序)

(1)unordered_map比map快

vector<node> v;
unordered_map<string,int> m;
//可直接将map内容插入vector中:
for(auto it:m)    v.push_back({it->first,it->second});

(2)如何让map根据value排序:

typedef pair<string,int> npair;
bool cmp2(const npair &a,const npair &b) {
	if(a.second!=b.second)	return a.second > b.second;
	else	return a.first < b.first;
}
map<string,int> site;
vector<npair> vsite(site.begin(),site.end()); //让map根据value排序 
sort(vsite.begin(),vsite.end(),cmp2);
for(auto it=vsite.begin(); it!=vsite.end(); it++) {
	printf("%s %d\n",it->first.c_str(),it->second);
}

1155:堆的路径(DFS)

输出根到每个叶子节点的路径
满足i<=n但是2i>n && 2i+1>n的heap[i] 一定是叶结点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值