网络异常,图片无法展示
|
给你一个字符串 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
中只含有小写英文字母
解题思路
因为索引对关系中的字符可以任意交换,所以可以根据索引对数组,将对应字符维护到一个集合中。
然后将集合中的字符进行排序,根据排序后的结果组装结果字符串即可。
因为过程中需要频繁对集合进行合并,以及获取字符所在集合,所以可以需要借助并查集解题。
如果你对 并查集
还不了解,可以看我这一篇文章 数据结构-并查集,文中介绍了并查集的概念、应用场景以及手写实现的全过程。
动画演示
网络异常,图片无法展示
|
代码实现
class UnionSet { constructor(n){ // 初始化节点数量数组 this.size = Array(n).fill(1); // 初始化集合列表,每一个节点为一个集合 this.list = Array(n); for(let i = 0;i<n;i++){ this.list[i] = i; } } // 递归获取元素所在集合根节点 find(x){ if(this.list[x] === x) return x; // 获取到元素所在集合根节点 const root = this.find(this.list[x]) // 将当前节点挂载为根节点子节点,压缩路径 this.list[x] = root; return root; } // 合并两个集合 merge(a,b){ // 获取两元素所在集合的根节点 const rootA = this.find(a),rootB = this.find(b); // 如果根节点相同,则两元素处于同一集合,无需合并 if(rootA === rootB) return; // 如果 a 所在集合元素数量更多,将 b 所在集合合并到 a 所在集合 if(this.size[rootA]>this.size[rootB]){ this.list[rootB] = rootA; this.size[rootA] += this.size[rootB] }else{ // 反之将 a 所在集合合并到 b 所在集合 this.list[rootA] = rootB; this.size[rootB] += this.size[rootA] } } } var smallestStringWithSwaps = function(s, pairs) { // 获取字符串长度 const len =s.length, // 创建并查集实例 unionset = new UnionSet(len); // 遍历索引对 for(let i = 0;i<pairs.length;i++){ // 将对应字符合并到一个集合 unionset.merge(pairs[i][0],pairs[i][1]) } // 获取集合 const map = new Map(); for(let i = 0;i<len;i++){ const root = unionset.find(i); if(map.has(root)){ const item = map.get(root); item.vals.push(s[i]) item.inds.push(i) }else{ map.set(root,{vals:[s[i]],inds:[i]}) } } // 创建结果字符数组 const arr = Array(len); // 遍历集合 map.forEach(item => { // 对每个集合中的字符及下标排序 item.vals.sort(); item.inds.sort((a,b) => a-b); // 根据排序后的结果组装结果字符串 for(let i = 0;i<item.vals.length;i++){ arr[item.inds[i]] = item.vals[i] } }) // 返回结果值 return arr.join('') }; 复制代码
至此我们就完成了 leetcode-1202-交换字符串中的元素
如有任何问题或建议,欢迎留言讨论!