题目描述
给你一个字符串 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^50 <= pairs.length <= 10^50 <= pairs[i][0], pairs[i][1] < s.lengths中只含有小写英文字母
解题思路
- 1.交换;2.按字典排序;3.拼接字符串
- 1.根据这个二维数组pairs,获取可以交换的字母,然后可以交换的字母组成一组。
- 2.对组内的字母进行排序。
- 3.接着根据字符串中组号获取我们组内最小字符进行拼接。最后得到的字符串就是所需要的进行排过序的字符串
动画演示
代码实现:
var smallestStringWithSwaps = function(s, pairs) {
let len = s.length;
let uf = new UnionFind(len);
// 1.将可以进行交换的字符进行连通
for(let i = 0; i < pairs.length; i ++){//选拿到索引对,遍历数组
// 拿到里面的每一对数组
let index1 = pairs[i][0],index2 = pairs[i][1];
// 拿到两个索引,进行联通
if(uf.findSet(index1) != uf.findSet(index2)){
uf.unite(index1,index2);
}
}
// 2.先拿到联通后的数组
let fa = uf.parent;
// 2.将联通的字符存入到一个新的数组里面进行排序
let vec = new Array(len).fill(0).map(()=> new Array());//根据祖先节点进行分组,val 是组里面字符串的集合
for(let i = 0; i < len; i++){
fa[i] = uf.findSet(i);
vec[fa[i]].push(s[i]);
}
for(let i = 0; i < len; i++){ // 按着字典序排序
if(vec[i].length > 0 ){
vec[i].sort((a,b) => a.charCodeAt() - b.charCodeAt())
}
}
// 3.通过原始字符坐标,获取字符串的组号,拼接字符串
// 记录每一组字符串位置
let p = new Array(len).fill(0);
// 输出字符的数组
let ans = [];
for(let i = 0; i < len; i++){
ans.push('1');
}
// 通过原始字符坐标,获取字符串的组号,拼接字符串
for(let i = 0 ; i < len; i++){
ans[i] = vec[fa[i]][p[fa[i]]];
p[fa[i]] ++;
}
// 拼接字符join
return ans.join('');
};
class UnionFind{
constructor(n){
this.parent = new Array(n).fill(0).map((val,index)=>index);
this.rank = new Array(n).fill(0);
this.setCount = n;
}
findSet(index){
if(this.parent[index] != index){
this.parent[index] = this.findSet(this.parent[index])
}
return this.parent[index];
}
unite(index1,index2){
let root1 = this.findSet(index1);
let root2 = this.findSet(index2);
if(root1 != root2){
if(root1 < root2){
[root1,root2] = [root2,root1];
}
this.parent[root2] = root1;
this.rank[root1] += this.rank[root2];
this.setCount--;
}
}
getCount(){
return this.setCount()
}
connected(index1,index2){
let root1 = this.findSet(index1),root2 = this.findSet(index2);
return root1 == root2
}
}
至此我们就完成了leetcode-1202-交换字符串中的元素