LC1202.交换字符串中的元素

LC1202.交换字符串中的元素
image.png

思路:并查集 + 优先队列

  • 允许进行交换的一部分位置,可以将其视作一个集合。集合内部自由排序,排序到字典序最小即可。
  • 确定“允许自由交换的一部分位置”,通过并查集来完成。特定集合的共同特征在于,其共享一个“代表”,即相同的find(s[i]
  • 建立“当前位置的集合代表”find(s[i])和对应“优先队列”priority_queue的一一映射。优先队列当中存储了当前集合的所有元素。
  • 遍历数组,对于当前位置而言s[i],越靠前的位置越希望有字典序小的元素,因此,将find(s[i])对应的优先队列的最小元素赋给当前位置,同时弹出最小元素。如果元素不在可交换队列当中,那么它的优先队列只有一个元素,就是原来的元素。

    代码:

    ```cpp class UF { private:

    1. vector<int> fa, r;

    public:

    1. UF(int n): fa(n), r(n, 1) {
    2. iota(fa.begin(), fa.end(), 0);
    3. }
    4. int find(int x) {
    5. if (fa[x] != x) {
    6. fa[x] = find(fa[x]);
    7. }
    8. return fa[x];
    9. }
    10. void merge(int x, int y) {
    11. x = find(x), y = find(y);
    12. if (x != y) {
    13. if (r[x] <= r[y]) {
    14. fa[x] = fa[y];
    15. } else {
    16. fa[y] = fa[x];
    17. }
    18. if (r[x] == r[y]) {
    19. r[y] += 1;
    20. }
    21. }
    22. }
    23. bool is_connected(int x, int y) {
    24. return find(x) == find(y);
    25. }

    };

class Solution { public: string smallestStringWithSwaps(string s, vector>& pairs) { int n = s.size(); UF uf(n); for (int i = 0, np = pairs.size(); i < np; i++) { uf.merge(pairs[i][0], pairs[i][1]); }

  1. unordered_map<int, priority_queue<int, vector<int>, greater<int>>> mp;
  2. for (int i = 0; i < n; i++) {
  3. // priority_queue<int, vector<int>, greater<int>> q;
  4. // mp[uf.find(i)] = q;
  5. mp[uf.find(i)].push(s[i] - 'a');
  6. // cout << uf.find(i) << " " ;
  7. }
  8. for (int i = 0; i < n; i++) {
  9. s[i] = mp[uf.find(i)].top() + 'a';
  10. mp[uf.find(i)].pop();
  11. }
  12. return s;
  13. }

}; ```