可以让数组中的某个数加1,求加几次之后数组中所有的数都是唯一的。
先将数组排序,现在遍历数组,如果当前数大于等于前一个数加1,则说明不用处理,令前一个数等于当前数,如果小于前一个数加1,则要把它变到前一个数加1,并把前一个数变成前一个数加1.
class Solution {
public int minIncrementForUnique(int[] A) {
if(A==null || A.length<2)return 0;
Arrays.sort(A);
int res=0;
int preNum=A[0];
for(int i=1;i<A.length;i++){
if(A[i]>=preNum+1){
preNum=A[i];
}else{
res+=preNum+1-A[i];
preNum++;
}
}
return res;
}
}
并查集
遍历元素,将这个数组放到连通分量中,如果发现这个元素不能放到指定位置,就要顺次找到这个连通分量的最大值,然后将这个元素放在下一个,然后将它加入连通分量。
并查集就有两个操作,第一个是合并(union),第二个是查询find这个元素的连通分量的根节点(find)。(两个元素都查根节点可以找到他们是不是在一个连通分量中)。
初始化一般就是有多少个元素制造多少个连通分量,然后进行别的操作。可以用数组或者是hashmap表示。一个元素为x,则它的上一个元素为f(x),在数组中也就意味着值等于下标的值就是根节点。
find也就是找到根节点,如果x等于f(x),意味着这就是根节点,否则返回find(f(x))。可以进行的优化就是将一个连通分量中所有的节点都连在根节点上。这样的话find操作就是:如果x等于f(x),则返回x,如果不等于,则将f(x)的父节点设置为f(x),并返回f(x)。
union就是找到两个集合的根节点,然后让一个集合的根节点的上一个元素为另一个集合的根节点。f(f(x))=f(y)。即让x集合的根节点的上一个节点为y的根节点。
则这个题中我们将连通分量中最大的元素设为根节点。如果遍历到新元素时不在并查集中,就将它加入,并且把左边右边的都加入,连起来。(加入就是创造新的连通分量,需要和原来的连通分量进行合并)
如果在并查集中,说明这个数重复了,需要增加,增加到此时连通分量的根节点+1.记一下move的值。将增加过的数加入连通分量,(还是需要合并左和右)
class Solution {
public int minIncrementForUnique(int[] A) {
int len = A.length;
if (len == 0) {
return 0;
}
UnionFind unionFind = new UnionFind();
int res = 0;
for (int num : A) {
if (unionFind.contains(num)) {//如果此时的值在并查集中,说明要自增
int root = unionFind.find(num);
int add = root + 1;
res += (add - num);
unionFind.init(add);
} else {
unionFind.init(num);//如果不在并查集中,说明不用自增。
}
}
return res;
}
private class UnionFind {
private int[] parent;//用数组实现
public UnionFind() {//构造函数
this.parent = new int[79999];
// 应初始化成为 -1,表示这个元素还没放进并查集
Arrays.fill(parent, -1);
}
public void init(int x) {//初始化
parent[x] = x;//左右如果都在并查集则合并。
if (x > 0 && parent[x - 1] != -1) {
union(x, x - 1);
}
if (parent[x + 1] != -1) {
union(x, x + 1);
}
}
public boolean contains(int x) {//表示这个节点在不在并查集中
return parent[x] != -1;
}
public int find(int x) {
if(x==parent[x])return x;
else{
parent[x]=find(parent[x]);
return parent[x];
}
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
// 注意:根据这个问题的特点
// 只能把小的结点指向大的结点
if (rootX < rootY) {
parent[rootX] = rootY;
}
if (rootY < rootX) {
parent[rootY] = rootX;
}
}
}
}