1202.交换字符串中的元素
首先,我不得不吐槽一下这个题目,我一开始以为是根据Pairs里面的东西进行操作。
实际上,这个题目说的意思就是:
- 根据Pairs把放在一起的元素归为1类
- 将同类的元素按照从小到达排序。
- 输出最后的字符串。
收获:
1. 将String转化为Char的数组: s.toCharArray()
2. 类似Python的字符串诸位构造:StringBuilder和.append()
思路一:并查集
第一步:我们通过并查集把相同的元素合并为一类
第二步:我们利用HashMap,Key是同类元素第一个元素的下标,Value是一个同类元素的PriorityQueue,字符小的在树的顶端,我们构建这样一个Priority Queue。
第三步:我们从小到大遍历String,每次找到他对应的类别,找到其对应类别中最小的元素即可,又因为我们每次移动一个字符,就会从Priority Queue中Pop出一个字符,所以我们输出字符的长度应该和原来字符的长度是一样的。
class Solution {
public String smallestStringWithSwaps(String s, List<List<Integer>> pairs) {
if(pairs.size()==0)
return s;
// 第一步:利用并查集,将相同的元素合并为1类
int len = s.length();
UnionFind uf = new UnionFind(len);
for(List<Integer> pair : pairs)
uf.union(pair.get(0),pair.get(1));
// 将String转化为Char的数组
char[] charArray = s.toCharArray();
// 第二步:构建HashMap
HashMap<Integer,PriorityQueue<Character>> hm = new HashMap<>();
for(int i=0;i<len;i++){
int parenti = uf.find(i);
// 如果已经键入这个类别了,则找到对应的Pq再添加一个新的元素
if(hm.containsKey(parenti))
hm.get(parenti).offer(charArray[i]);
else{
PriorityQueue<Character> tmp = new PriorityQueue<>();
tmp.add(charArray[i]);
hm.put(parenti,tmp);
}
}
// 第三部:重组最后的答案字符串
StringBuilder sb = new StringBuilder();
for(int i=0;i<len;i++){
int parenti = uf.find(i);
sb.append(hm.get(parenti).poll());
}
return sb.toString();
}
}
class UnionFind{
int[] element;
int[] rank; //真正有用的是父节点
public UnionFind(int N){
this.rank = new int[N];
this.element = new int[N];
for(int i=0;i<N;i++)
this.element[i]=i;
}
//带有路径压缩
public int find(int i){
if(element[i]==i)
return i;
else{
element[i]=find(element[i]);
}
return element[i];
}
public void union(int i,int j){
int parenti = find(i);
int parentj = find(j);
if(rank[i]<rank[j]){
element[parenti]=parentj;
}
else if(rank[i]>rank[j]){
element[parentj]=parenti;
}
else{
element[parentj]=parenti;
rank[parenti]++;
}
}
}