一、PAT A1144 The Missing Number
- 散列的思想,最小的正整数肯定不大于序列个数 + 1,参考代码如下。
#include<cstdio>
using namespace std;
const int maxn = 100005;
int h[maxn], n, t;
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &t);
if (t > 0 && t <= n)
h[t]++;
}
for (int i = 1; i <= n+1; i++)
if (h[i] == 0) {
printf("%d\n", i);
break;
}
return 0;
}
二、PAT A1145 Hashing - Average Search Time
- 散列表的单向平方探测。注意散列时探测指针范围为 0~MSize-1,因为指针为 MSize 时的散列值和为 0 时的散列值是一样的;查找时探测指针范围为 0~MSize,因为要确认回到第 0 次探测的位置(其实我觉得没必要啊)。参考代码如下。
#include<cstdio>
#include<math.h>
using namespace std;
const int maxn = 10010;
int h[maxn], t, MSize, N, M;
bool is_prime(int n) {
if (n == 0 || n == 1) return false;
int t = (int)sqrt(n);
for (int i = 2; i <= t; i++)
if (n % i == 0) return false;
return true;
}
bool hash(int n) {
for (int i = 0; i < MSize; i++) {
int t = (n % MSize + i * i) % MSize;
if (h[t] == 0) {
h[t] = n;
return true;
}
}
return false;
}
int find(int n) {
int cnt = 0;
for (int i = 0; i <= MSize; i++) {
cnt++;
int t = (n % MSize + i * i) % MSize;
if (h[t] == 0) break;
else if (h[t] == n) break;
}
return cnt;
}
int main() {
scanf("%d%d%d", &MSize, &N, &M);
while (true) {
if (is_prime(MSize))
break;
MSize++;
}
for (int i = 0; i < N; i++) {
scanf("%d", &t);
if (!hash(t))
printf("%d cannot be inserted.\n", t);
}
int sum = 0;
for (int i = 0; i < M; i++) {
scanf("%d", &t);
sum += find(t);
}
printf("%.1f\n", sum * 1.0 / M);
return 0;
}
三、PAT A1146 Topological Order
- 判断是否为拓扑排序。用邻接表存储图,记录每个点的入度。按顺序遍历每一个点,如果这个点的入度不为 1,则不为拓扑序列,否则将这个点的指向的所有点的入度减 1,然后判断下一个点。参考代码如下。
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 1010;
vector <int> adj[maxn];
int in_degree[maxn], seq[maxn], temp_in_degree[maxn];
int N, M, K;
bool judge() {
memcpy(temp_in_degree, in_degree, sizeof(in_degree));
for (int i = 1; i <= N; i++) {
int u = seq[i];
if (temp_in_degree[u] == 0) {
for (int j = 0; j < adj[u].size(); j++) {
int v = adj[u][j];
temp_in_degree[v]--;
}
}
else return true;
}
return false;
}
int main() {
scanf("%d%d", &N, &M);
int v1, v2;
while (M--) {
scanf("%d%d", &v1, &v2);
adj[v1].push_back(v2);
in_degree[v2]++;
}
scanf("%d", &K);
bool first = true;
for (int cnt = 0; cnt < K; cnt++) {
for (int i = 1; i <= N; i++)
scanf("%d", &seq[i]);
if (judge()) {
if (!first) printf(" ");
printf("%d", cnt);
first = false;
}
}
return 0;
}
四、PAT A1147 Heaps
- 判断是否为堆,然后再后续遍历。因为是用完全二叉树存储的,所以很简单啦。参考代码如下。
#include<cstdio>
using namespace std;
const int maxn = 1010;
int heap[maxn], M, N;
bool max_heap, min_heap, first;
void judge() {
max_heap = true, min_heap = true;
for (int i = 1; i <= N / 2; i++) {
if (heap[i] > heap[2 * i] || (2 * i + 1 <= N && heap[i] > heap[2 * i + 1]))
min_heap = false;
else if (heap[i] < heap[2 * i] || (2 * i + 1 <= N && heap[i] < heap[2 * i + 1]))
max_heap = false;
}
}
void post(int r) {
if (r > N) return;
post(2 * r);
post(2 * r + 1);
if (!first) printf(" ");
printf("%d", heap[r]);
first = false;
}
int main() {
scanf("%d%d", &M, &N);
while (M--) {
for (int i = 1; i <= N; i++)
scanf("%d", &heap[i]);
judge();
if (min_heap) printf("Min Heap\n");
else if (max_heap) printf("Max Heap\n");
else printf("Not Heap\n");
first = true;
post(1);
printf("\n");
}
return 0;
}