难度:中等
题目:
给你一个字符串 s ,以及该字符串中的一些「索引对」数组 pairs ,其中 pairs[i] = [a, b] 表示字符串中的两个索引(编号从 0 开始)。
你可以 任意多次交换 在 pairs 中任意一对索引处的字符。
返回在经过若干次交换后,s 可以变成的按字典序最小的字符串。
示例 1:
输入:s = "dcab", pairs = [[0,3],[1,2]]
输出:"bacd"
解释:
交换 s[0] 和 s[3], s = "bcad"
交换 s[1] 和 s[2], s = "bacd"
示例 2:
输入:s = "dcab", pairs = [[0,3],[1,2],[0,2]]
输出:"abcd"
解释:
交换 s[0] 和 s[3], s = "bcad"
交换 s[0] 和 s[2], s = "acbd"
交换 s[1] 和 s[2], s = "abcd"
示例 3:
输入:s = "cba", pairs = [[0,1],[1,2]]
输出:"abc"
解释:
交换 s[0] 和 s[1], s = "bca"
交换 s[1] 和 s[2], s = "bac"
交换 s[0] 和 s[1], s = "abc"
提示:
1 <= s.length <= 10^5
0 <= pairs.length <= 10^5
0 <= pairs[i][0], pairs[i][1] < s.length
s 中只含有小写英文字母
Related Topics
深度优先搜索
广度优先搜索
并查集
哈希表
字符串
重点!!!解题思路
第一步:
明确解题手段
类似于此种连通性问题均能使用并查集来实现
第二步:
已经给定了要排序的字母下标,
我们只需要使排序的字母保持字典序最小即可。
保持字典序最小可使用小顶堆来维持一个排序,
即我们此题要使用并查集和堆结合的方式来实现。
第三步:
将给定的字母下标使用并查集相连,
再次遍历时,如果两个字母下标是同一个根节点的,
那么就加入到同一个小顶堆中。
最后输出时使用StringBuffer来拼接堆poll的元素
源码:
class UnionFind {
//记录每个节点的根节点
int[] parent;
//记录每个子集的节点数
int[] rank;
//记录并查集中的联通分量数量
int count;
public UnionFind(int n){
count=n;
parent=new int[n];
for (int i=0;i<n;i++){
parent[i]=i;
}
rank=new int[n];
Arrays.fill(rank,1);
}
//路径压缩
public int find(int ind){
if (parent[ind]!=ind){
parent[ind]=find(parent[ind]);
}
return parent[ind];
}
//按秩合并
public void unite(int ind1,int ind2){
int root1=find(ind1),root2=find(ind2);
if (root1!=root2){
if (rank[root1]<rank[root2]){
int temp=root2;
root2=root1;
root1=temp;
}
parent[root2]=root1;
rank[root1]+=rank[root2];
count--;
}
}
public int getCount(){
return count;
}
public boolean connected(int ind1,int ind2){
return find(ind1)==find(ind2);
}
}
class Solution {
public String smallestStringWithSwaps(String s, List<List<Integer>> pairs) {
UnionFind uf = new UnionFind(s.length());
for (List<Integer> pair : pairs) {
uf.unite(pair.get(0),pair.get(1));
}
Map<Integer, PriorityQueue<Character>> map = new HashMap<>();//使用map集合来存储同根的元素
for (int i=0;i<s.length();i++){
int root=uf.find(i);
map.computeIfAbsent(root,key->new PriorityQueue<>()).offer(s.charAt(i));//如果不存在root的key值,则创建一个新堆加入到map中。如果存在root的key值,则将value的堆拿出来继续添加元素
}
StringBuffer res=new StringBuffer();
for (int i=0;i<s.length();i++){
int root= uf.find(i);
res.append(map.get(root).poll());//每次拼接的都是堆poll出来的最小字典序字母
}
return res.toString();
}
}
解题结果:
如果您还有什么疑问或解答有问题,可在下方评论,我会及时回复。
系列持续更新中,点个订阅吧