PAT题目答案与经验总结1(持续更新,大家放心关注)

1115 Counting Nodes in a BST (30 分)

题目链接

https://pintia.cn/problem-sets/994805342720868352/problems/994805355987451904

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef struct node * tree;
struct node{
	int val;
	tree left,right;
};
unordered_map<int,int> cnt;
int pos=1;
tree insert(int t,tree root)
{
	if(root==NULL){
		root = new node();
		root->val=t;
		root->left=root->right=NULL;
	}
	else if(t<=root->val)
		root->left=insert(t,root->left);
	else if(t>root->val)
		root->right=insert(t,root->right);
	return root;
}

void bfs(tree root)
{
	queue<tree> q;
	q.push(root);
	tree last=q.back();
	while(q.size())
	{
		tree t=q.front();
		q.pop();
		if(t->left!=NULL) q.push(t->left);
		if(t->right!=NULL) q.push(t->right);
		cnt[pos]++;
		if(t==last){
			pos++;
			last=q.back();
		}
	}
}

void dfs(tree root,int depth)
{
	if(!root){
		pos=max(pos,depth);
		return;
	}
	cnt[depth]++;
	dfs(root->left,depth+1);
	dfs(root->right,depth+1); 
}

int main()
{
	int n,t;
	cin>>n;
	tree root=NULL;
	while(n--)
	{
		cin>>t;
		root = insert(t,root);
	}
//	bfs(root);
	dfs(root,1);
	printf("%d + %d = %d",cnt[pos-1],cnt[pos-2],cnt[pos-1]+cnt[pos-2]);
}

注意事项

  1. root->left=insert(t,root->left);这行代码的函数命insert我一开始竟然没写,确实是好久没建树了,考试前要注意练习
  2. dfs中当节点为NULL时,必须要写return,否则无法退出
  3. 这道题dfs和bfs均可,建议大家都尝试一下

1139 First Contact (30 分)

题目链接

https://pintia.cn/problem-sets/994805342720868352/problems/994805344776077312

AC代码

#include<bits/stdc++.h>
using namespace std;
struct node{
	int f1,f2;
};
unordered_map<int,int> gender,team;
unordered_map<int,vector<int>> f;
bool cmp(node x,node y){
	return x.f1!=y.f1?x.f1<y.f1:x.f2<y.f2;
}
int main()
{
	int n,m,k;
	cin>>n>>m;
	while(m--)
	{
		string s1,s2;
		int t1,t2,flag1=1,flag2=1;
		cin>>s1>>s2;
		if(s1[0]=='-') flag1=-1;
		if(s2[0]=='-') flag2=-1;
		t1=abs(stoi(s1));
		t2=abs(stoi(s2));
		gender[t1]=flag1;
		gender[t2]=flag2;
		f[t1].push_back(t2);
		f[t2].push_back(t1);
		team[t1*10000+t2]=team[t2*10000+t1]=1;
	}
	cin>>k;
	while(k--)
	{
		vector<node> ans;
		int t1,t2;
		cin>>t1>>t2;
		t1=abs(t1),t2=abs(t2);
		for(int i=0;i<f[t1].size();i++)
		{
			for(int j=0;j<f[t2].size();j++)
			{
				int f1=f[t1][i],f2=f[t2][j];
				if(f1==t2||f2==t1) continue;
				if(team[f1*10000+f2]&&gender[f1]==gender[t1]&&gender[f2]==gender[t2])
					ans.push_back({f1,f2}); 
			}
		}
		sort(ans.begin(),ans.end(),cmp);
		cout<<ans.size()<<endl;
		for(int i=0;i<ans.size();i++)
			printf("%04d %04d\n",ans[i].f1,ans[i].f2);
	}
}

注意事项

  1. 之所以在输入阶段大费周章采用字符串判断正负,就是为了对0000做判断,因为如果整数判断,0本身的正负无法确定(即-0000无法判断)
  2. A爱B,但A、B不能是朋友(强烈吐槽,恋爱不都是从朋友到女(男)朋友吗,一见钟情除外。关键是题目里并没有相关的提示信息啊,哪位朋友如果能找到提示信息可以发在评论区里)

1142. Maximal Clique (25分)

题目链接

https://pintia.cn/problem-sets/994805342720868352/problems/994805343979159552

AC代码

#include<bits/stdc++.h>
using namespace std;
int a[205][205];
int main()
{
	int nv,ne,m,k,t;
	cin>>nv>>ne;
	while(ne--)
	{
		int t1,t2;
		cin>>t1>>t2;
		a[t1][t2]=a[t2][t1]=1;
	}
	cin>>m;
	while(m--)
	{
		int flag1=1,flag2=1,vis[nv+1]={0};
		fill(vis,vis+nv,0);
		cin>>k;
		if(k==0)
		{
			cout<<"Not a Clique"<<endl;
			continue;
		}
		vector<int> ans;
		for(int i=0;i<k;i++)
		{
			cin>>t;
			vis[t]=1;
			ans.push_back(t);
		}
		for(int i=0;i<k-1;i++)
		{
			for(int j=i+1;j<k;j++)
			{
				if(a[ans[i]][ans[j]]==0)
				{
					flag1=0;
					break;
				}
				if(flag1==0) break;
			}
		}
		if(flag1==0) cout<<"Not a Clique"<<endl;
		else
		{
			for(int i=1;i<=nv;i++)
			{
				if(vis[i]==0)
				{
					for(int j=0;j<k;j++)
					{
						if(a[i][ans[j]]==0)
							break;
						if(j==k-1) flag2=0;
					}
				}
				if(flag2==0) 
				{
					cout<<"Not Maximal"<<endl;
					break; 
				}
			}
			if(flag2==1) cout<<"Yes"<<endl; 
		}
		
	}
} 

注意事项

  1. flag1,flag2两个变量的判断顺序——要在第一个判断是否连通后,再进入maximal的判断
  2. 我自己的代码在设置判断点是否在待测数组的vis时,将范围设置为了nv,即vis[nv]={0},但发现测试点2、3一直过不去,在将其改为vis[nv+1]={0}后,便可全部通过(测试了好久才找到,这是因为序号是从1到nv排序的)

1143 Lowest Common Ancestor (30 分)

题目链接

https://pintia.cn/problem-sets/994805342720868352/problems/994805343727501312

AC代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int m,n;
	cin>>m>>n;
	vector<int> pre(n);
	unordered_map<int,int> vis;
	for(int i=0;i<n;i++)
	{
		cin>>pre[i];
		vis[pre[i]]=1;
	}
	while(m--)
	{
		int x,y,root;
		cin>>x>>y;
		if(vis[x]==0&&vis[y]==0) 
		{
			printf("ERROR: %d and %d are not found.\n",x,y);
			continue;
		}
		else if(vis[x]==0||vis[y]==0)
		{
			printf("ERROR: %d is not found.\n",vis[x]==0?x:y);
			continue;
		}
		for(int i=0;i<n;i++)
		{
			root=pre[i];
			if((x<root&&y>root)||(x>root&&y<root)||x==root||y==root)
				break;	
		}	
		if((x<root&&y>root)||(x>root&&y<root))
			printf("LCA of %d and %d is %d.\n",x,y,root);
		else if(x==root)
			printf("%d is an ancestor of %d.\n",x,y);
		else if(y==root)
			printf("%d is an ancestor of %d.\n",y,x);
	}	
} 

注意事项

这道题的关键就是LCA的判断方法,我原先用的是递归(自己将前序序列排序得到中序数组,并按传统方法寻找),但在参考了柳神的文章后,我发现这道题完全可以用循环做。

因为这道题中的BST树满足左小右大的准则,那么通过数字大小的比较就可以知道节点的相应位置,进而做出判断

当然这是这道题独有的解题方法,因为在传统的二叉树中,数字大小与其在树中的位置是无关的,还是要用递归做。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值