【数据结构-并查集】力扣1202. 交换字符串中的元素

给你一个字符串 s,以及该字符串中的一些「索引对」数组 pairs,其中 pairsi = a, b 表示字符串中的两个索引(编号从 0 开始)。

你可以 任意多次交换 在 pairs 中任意一对索引处的字符。

返回在经过若干次交换后,s 可以变成的按字典序最小的字符串。

示例 1:

输入:s = "dcab", pairs = \[0,3,1,2]

输出:"bacd"

解释:

交换 s0 和 s3, s = "bcad"

交换 s1 和 s2, s = "bacd"

示例 2:

输入:s = "dcab", pairs = \[0,3,1,2,0,2]

输出:"abcd"

解释:

交换 s0 和 s3, s = "bcad"

交换 s0 和 s2, s = "acbd"

交换 s1 和 s2, s = "abcd"

示例 3:

输入:s = "cba", pairs = \[0,1,1,2]

输出:"abc"

解释:

交换 s0 和 s1, s = "bca"

交换 s1 和 s2, s = "bac"

交换 s0 和 s1, s = "abc"

提示:

1 <= s.length <= 10^5

0 <= pairs.length <= 10^5

0 <= pairsi0, pairsi1 < s.length

s 中只含有小写英文字母

并查集

cpp 复制代码
class UnionFind{
private:
    vector<int> parent;
public:
    UnionFind(int n){
        parent.resize(n);
        for(int i = 0; i < n; i++){
            parent[i] = i;
        }
    }

    void unite(int index1, int index2){
        parent[find(index2)] = find(index1);
    }

    int find(int index){
        if(parent[index] == index){
            return index;
        }
        parent[index] = find(parent[index]);
        return parent[index];
    }
};


class Solution {
public:
    string smallestStringWithSwaps(string s, vector<vector<int>>& pairs) {
        int n = s.size();
        UnionFind uf(n);

        for(auto& c : pairs){
            uf.unite(c[0], c[1]);
        }

        unordered_map<int, priority_queue<char, vector<char>, greater<>>> hash;
        for(int i = 0; i < n; i++){
            auto& c = s[i];
            hash[uf.find(i)].push(c);
        }

        string res = "";
        for(int i = 0; i < n; i++){
            res += hash[uf.find(i)].top();
            hash[uf.find(i)].pop();
        }
        return res;
    }
};

这道题首先需要掌握并查集的知识,不熟悉该数据结构的可以先去看我主页力扣990题解。这道题目我们通过观察可以发现,只要索引对之间有交互,那么这些索引对所覆盖的索引的字符之间可以通过多次交换而替换成其中的任意一个字符。通过这个特性,我们就可以将索引对之间有交集的字符作为一个连通块,连通块为了排序字符之间的字典序,所以采用了小根堆的数据结构,保证连通块之间的字符是按字典序升序排列。

那么我们最后就可以定义一个变量res来记录答案,我们只需要遍历字符串从0到n-1的索引,然后将该字符索引所在连通集中的字典序最小的字符推入到res中,然后再将最小字符从连通集的小根堆中弹出即可。

举个例子

输入:s = "dcab", pairs = \[0,3,1,2]

字符d和b是一个连通集,字符c和a是一个连通集。

那么在计算res的时候,遍历字符串s,i=0所在连通集b是字典序最小字符,那么就将b推入res中,然后i=1所在连通集a是字典序最小的字符,将a推入到res中,再遍历到i=2,此时该连通集的小根堆中只剩下了c,那么只能推入c到res中,最后i=3,此时该连通集中的小根堆只剩下了d,推入d到res中,最后输出:"bacd"。

相关推荐
垆边人似月.7 分钟前
华为题:任务调度
数据结构·c++·算法
Logic10114 分钟前
C语言/数据结构字符串题解:解压缩“字符+次数“格式——多位数字处理与字符串还原
c语言·数据结构·字符串·模拟·时间复杂度·空间复杂度·算法题
信奥卷王17 分钟前
[GESP202506 六级] 最大因数(含视频)
数据结构·算法
局部有解23 分钟前
Leetcode - 42 接雨水(一维)
数据结构·c++·算法·leetcode
专注API从业者1 小时前
告别手工盯盘:用 Open‑Claw 搭建电商商品自动化监控与数据分析实战
运维·数据结构·数据挖掘·数据分析·自动化
Logic1011 小时前
C语言/数据结构位运算题解:异或XOR找出糖葫芦派对中的“独一无二山楂果数量“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Tisfy2 小时前
LeetCode 3723.数位平方和的最大值:构造
数学·算法·leetcode·字符串·题解
benchmark_cc3 小时前
批量获取股票数据后,如何统一转换成 DataFrame?从数据结构到量化研究的完整实践
数据结构·python·数据分析·量化交易·股票数据·quantdash
溪语流沙3 小时前
面试加分项!Manacher:O(n)求最长回文子串的对称之美
java·python·leetcode·面试·职场和发展
啵啵啵鱼3 小时前
第三章 栈、队列和数组相关结构
java·数据结构·栈·队列