第十届蓝桥杯 修改数组—并查集的简单应用–JAVA写法
题目
给定一个数组,数组中可能有重复的元素,现在要将其改为没有重复整数的数组。
修改方法:当修改第i个元素是,查看该元素之前是否出现过,如果出现过,会把第i个元素+1;如果还是重复继续+1。
输入格式: 第一行包含一个整数N
第二行包含N个整数
输出则把数组一次输出
样例:5
2 1 1 3 4
输出:2 1 3 4 5
思路
一开始大部分人应该会想到递归,但是单纯的递归数据几百个可能就撑不住了,而这题的要求中数组元素最多会达到100000个
这题比较好的方法就是利用并查集,不过一般在考场上还是需要一定实力才能想到。没关系,编程就是慢慢积累经验的过程。
至于并查集建议大家看看csdn上其他大佬的详解(一定要看)
代码和讲解
大家捋不清楚的建议拿一组数据试一试
比如2 1 1 3 4,首先输出就是2,然后并查集使得数组元素f【2】本来的2,+1变成了3,也就是之后再碰到2会直接输出3。后面都是同理。一定要去看并查集的文章理解后再看代码。
public class Main6 {
第十届研究生组试题G 修改数组(并查集应用)
static int[] f=new int[2000000];
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//获取第一行数据
int n=Integer.parseInt(sc.nextLine());
int[] data=new int[n];
//初始化f数组
for (int i = 1; i < f.length; i++) {
f[i]=i;
}
//获取第二行数据,放到数组中
for (int i = 0; i < n; i++) {
data[i]=sc.nextInt();
}
for (int i = 0; i < data.length; i++) {
int k=find(data[i]);
data[i]=k;
f[data[i]]=find(data[i]+1);
}
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]+" ");
}
}
//(并查集)
public static int find(int x) {
if(x==f[x]) {
return x;
}else {
f[x]=find(f[x]);
return f[x];
}
}
//以下是递归法,但是速度过慢,几十个数据就撑不住了
// public static void fun(int k,ArrayList<Integer> list) {
// for (int i=k; k < list.size(); k++) {
// boolean boo=false;
// for (int j = 0; j <i; j++) {
// if(list.get(i)==list.get(j)) {
// list.set(i,list.get(i)+1);
// boo=true;
// }
// }
// if(boo) {
// fun(k, list);
// }else {
// k++;
// fun(k, list);
// }
// }
//
// }
}