修改数组
- 1.题目
- 2.基本思想
- 3.代码实现
1.题目
给定一个长度为 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。
数据范围
1
≤
N
≤
1
0
5
,
1≤N≤10^5 ,
1≤N≤105,
1
≤
A
i
≤
1
0
6
1≤Ai≤10^6
1≤Ai≤106
输入样例:
5
2 1 1 3 4
输出样例:
2 1 3 4 5
2.基本思想
并查集
单链表式的并查集
-
p
[
i
]
p[i]
p[i]:单链表中的下一个节点
i i i所在树的根节点:从 i i i开始向右找第一个没被用过的位置
步骤:依次从第一个位置开始往后扫描,进行find(x),更新p[x]=x+1
eg:第二个1:从1开始找到第一个没被用过的,1更新为数字3,将3进行指针后移。
3.代码实现
import java.util.Scanner;
public class _1242修改数组 {
static Scanner sc = new Scanner(System.in);
static int N = 1100010;
static int p[] = new int[N];
static int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
public static void main(String[] args) {
int n = sc.nextInt();
for (int i = 1; i < N; i++) p[i] = i;//初始化 并查集
for (int i = 1; i <= n; i++) {
int x = sc.nextInt();
x = find(x);//找到 从 x 开始 第一个 没有被用过的数字
System.out.print(x);
p[x] = x + 1;//更新
}
}
}