PAT A1120~A1123

本文详细解析了PATA1120至PATA1123四个算法题目,涵盖FriendNumbers、DamnSingle、HamiltonianCycle及CompleteAVLTree等核心算法概念。通过示例代码,深入讲解了集合排序、夫妻关系映射、哈密尔顿环验证及AVL树的建立与遍历技巧。

一、PAT A1120 Friend Numbers

  1. 很简单啦。把每个数的 friend id 算出来用集合保存,集合里面会自动排序,最后输出即可。参考代码如下。
#include<cstdio>
#include<set>
using namespace std;

set <int> s;

int main() {
	int n, t;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &t);
		s.insert(t / 1000 + t % 1000 / 100 + t % 100 / 10 + t % 10);
	}
	printf("%d\n", s.size());
	bool first = true;
	for (auto it : s) {
		if (!first) printf(" ");
		printf("%d", it);
		first = false;
	}
	return 0;
}

二、PAT A1121 Damn Single

  1. 将每一对夫妻关系用 map 映射起来。然后先读入所有参会人员,用标志变量表示其到会了。再遍历一次所有参会人员,如果某个人的 cp 没有到会,则说明这个人是独自参会的。注意独自参会人数为 0 时是不需要输出换行的。参考代码如下。
#include<cstdio>
#include<string>
#include<vector>
#include<unordered_map>
#include<set>
using namespace std;

unordered_map<string, bool> come;
unordered_map<string, string> cp;
vector<string> v;
set <string> s;

int main() {
	int n, m;
	string cp1, cp2, p;
	scanf("%d", &n);
	cp1.resize(6); cp2.resize(6); p.resize(6);
	while (n--) {
		scanf("%s%s", &cp1[0], &cp2[0]);
		cp[cp1] = cp2;
		cp[cp2] = cp1;
	}
	scanf("%d", &m);
	while (m--) {
		scanf("%s", &p[0]);
		v.push_back(p);
		come[p] = true;
	}
	for (auto it : v) if (!come[cp[it]]) s.insert(it);
	printf("%d\n", s.size());
	bool first = true;
	for (auto it : s) {
		if (!first) printf(" ");
		printf("%s", &it[0]);
		first = false;
	}
	if (!first) printf("\n");
	return 0;
}

三、PAT A1122 Hamiltonian Cycle

  1. 根据所给路径遍历一次图,遍历时如果某个结点与下一个结点不连通或是这个结点已经被访问过了,则不为哈密尔顿环。否则设置这个结点已经被访问,遍历下一个结点。参考代码如下。
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 210;

bool G[maxn][maxn] = { false };

int main() {
	int N, M, K, n, v1, v2;
	scanf("%d%d", &N, &M);
	while (M--) {
		scanf("%d%d", &v1, &v2);
		G[v1][v2] = true;
		G[v2][v1] = true;
	}
	scanf("%d", &K);
	while (K--) {
		scanf("%d", &n);
		vector <int> v(n + 1);
		for (int i = 1; i <= n; i++)
			scanf("%d", &v[i]);
		if (v[1] != v[n]) printf("NO\n");
		else {
			vector <bool> vis(N + 1);
			bool cycle = true;
			for (int i = 1; i < n; i++) {
				if (vis[v[i]]) { cycle = false; break; }
				else if (G[v[i]][v[i + 1]]) vis[v[i]] = true;
				else { cycle = false; break; }
			}
			for (int i = 1; i <= N; i++)if (!vis[i]) { cycle = false; break; }
			if (cycle) printf("YES\n");
			else printf("NO\n");
		}
	}
	return 0;
}

四、PAT A1123  Is It a Complete AVL Tree

  1. 先建立 AVL 树,然后层次遍历,然后再判断是否为完全二叉树。判断是否为完全二叉树的时候这里又用到了层次遍历,先将所有结点(包括空结点)入队,当有空结点出队时停止入队。然后判断队列中的后续结点是否还有非空结点,若有则说明不为完全二叉树。参考代码如下。
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
struct node {
	int v;
	int height = 1;
	node* lchild = NULL;
	node* rchild = NULL;
};
bool first = true;
int get_height(node* root) {
	if (root == NULL) return 0;
	else return root->height;
}
int get_bal_factor(node* root) {
	return get_height(root->lchild) - get_height(root->rchild);
}
void update_height(node* &root) {
	root->height = max(get_height(root->lchild), get_height(root->rchild)) + 1;
}
void L(node* &root) {
	node* temp = root->rchild;
	root->rchild = temp->lchild;
	temp->lchild = root;
	update_height(root);
	update_height(temp);
	root = temp;
}
void R(node* &root) {
	node* temp = root->lchild;
	root->lchild = temp->rchild;
	temp->rchild = root;
	update_height(root);
	update_height(temp);
	root = temp;
}
void insert(node* &root, int v) {
	if (root == NULL) {
		root = new node;
		root->v = v;
		return;
	}
	if (v < root->v) {
		insert(root->lchild, v);
		update_height(root);
		if (get_bal_factor(root) == 2) {
			if (get_bal_factor(root->lchild) == 1) {
				R(root);
			}
			else if (get_bal_factor(root->lchild) == -1) {
				L(root->lchild);
				R(root);
			}
		}
	}
	else {
		insert(root->rchild, v);
		update_height(root);
		if (get_bal_factor(root) == -2) {
			if (get_bal_factor(root->rchild) == -1) {
				L(root);
			}
			else if (get_bal_factor(root->rchild) == 1) {
				R(root->rchild);
				L(root);
			}
		}
	} 
}
void level(node* root) {
	queue <node*> q;
	q.push(root);
	while (q.size()) {
		node* temp = q.front();
		if (!first) cout << ' ';
		cout << temp->v; first = false;
		q.pop();
		if(temp->lchild) q.push(temp->lchild);
		if(temp->rchild) q.push(temp->rchild);
	}
}
bool judge(node* root) {
	queue <node*> q;
	q.push(root);
	while (q.size()) {
		node* temp = q.front();
		if (!temp) break;
		q.pop();
		q.push(temp->lchild);
		q.push(temp->rchild);
	}
	while (q.size()) {
		if (q.front()) return false;
		q.pop();
	}
	return true;
}

int main() {
	int n, t;
	cin >> n;
	node* root = NULL;
	while (n--) {
		cin >> t;
		insert(root, t);
	}
	level(root); cout << endl;
	if (judge(root)) cout << "YES" << endl;
	else cout << "NO" << endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值