题目链接:http://oj.ecustacm.cn/problem.php?id=1459
首先,暴力超时。
超时的原因在于查询重复的数字。那么可以用并查集来维护这些相同的数字,同时用路径压缩来进一步节省时间。
详细请看代码注释:
注意,joinset里面存储的是可用的数字,当a==joinset[a],则a本身可用,当用a更新数组后,a就已被占用了,所以需要更新joinset[a]来存储下一个可用的数字。
建议手动跑一下样例,列出两个数组的值,更容易理解。
#include <iostream>
#include <math.h>
#include <bits/stdc++.h>
using namespace std;
int num[1000005];
int joinset[1000005];
int findset(int a)
{
if(a!=joinset[a])当前数字出现过,继续寻找可用的数字,路径压缩
{
joinset[a]=findset(joinset[a]);
}
return joinset[a];
}
int main()
{
int n, root;
cin>>n;
for(int i=1; i<1000005; i++)
joinset[i]=i;//初始化并查集
for(int i=1; i<=n; i++)
{
cin>>num[i];
root=findset(num[i]);//找寻根或者说可用的数字
num[i]=root;//更新数组
joinset[root]=findset(root+1);//当前可用结果root被占用,所以更新下标为root的值为下一个可用的值
}
for(int i=1; i<=n; i++)
{
cout<<num[i]<<" ";
}
cout<<endl;
return 0;
}