[蓝桥杯][2019年第十届真题]修改数组*(暴力/并查集)
题目描述
给定一个长度为 N 的数组 A = [A1, A2, · · · AN ],数组中有可能有重复出现 的整数。
现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改 A2,A3,··· ,AN。
当修改 Ai 时,小明会检查 Ai 是否在 A1 ∼ Ai−1 中出现过。如果出现过,则 小明会给 Ai 加上 1 ;如果新的 Ai 仍在之前出现过,小明会持续给 Ai 加 1 ,直 到 Ai 没有在 A1 ∼ Ai−1 中出现过。
当 AN 也经过上述修改之后,显然 A 数组中就没有重复的整数了。 现在给定初始的 A 数组,请你计算出最终的 A 数组
输入
第一行包含一个整数 N。 第二行包含N个整数A1,A2,··· ,AN
输出
输出N个整数,依次是最终的A1,A2,··· ,AN。
样例输入
5 2 1 1 3 4
样例输出
2 1 3 4 5
提示
对于 80% 的评测用例,1 ≤ N ≤ 10000。
对于所有评测用例,1 ≤ N ≤ 100000,1 ≤ Ai ≤ 1000000。
一开始的思路
- 遍历数组,记录已存在的数字,当遇到一个数字已经存在,就将它加一,一直加到这个数字从未出现过
- 这个思路在N=10000时会超时
代码
#include<iostream> #include<cstring> #include<map> using namespace std; #define MAXN 10001 /* 5 2 1 1 3 4 2 1 3 4 5 */ int main() { int n; cin >> n; int A[MAXN]; int B[MAXN]; memset(B, 0, sizeof(B)); for (int i = 0; i < n; i++) { cin >> A[i]; } B[A[0]] = 1; for (int i = 1; i < n; i++) { if (B[A[i]] == 0) B[A[i]] = 1; else { while (B[A[i]]!=0) { A[i]++; } B[A[i]] = 1; } } for (int i = 0; i < n-1; i++) { cout << A[i]<<" "; } cout << A[n - 1]; return 0; }
并查集
- 这里参考了网上大佬们的博客,这里用到了并查集的思想,距离学数据结构已经快一年半了,早就忘了这是什么了,附上链接:https://www.cnblogs.com/cyanigence-oi/p/11774190.html
- 这个思路还不是很明白,先留个坑吧
#include<iostream> using namespace std; #define MAXN 100001 int A[MAXN], B[MAXN]; /* 5 2 1 1 3 4 2 1 3 4 5 */ int get(int x) { return B[x] == x ? x : get(B[x]); } int main() { int n; cin >> n; for (int i = 0; i < MAXN;i++) { B[i] = i; } for (int i = 0; i < n; i++) { cin >> A[i]; int res = get(A[i]); A[i] = res; B[A[i]] = get(res + 1); } for (int i = 0; i < n-1; i++) { cout << A[i]<<" "; } cout << A[n - 1]; return 0; }