【並查集】B011_LC_交換字符串中的元素(Map + PQ)

一、Problem

You are given a string s, and an array of pairs of indices in the string pairs where pairs[i] = [a, b] indicates 2 indices(0-indexed) of the string.

You can swap the characters at any pair of indices in the given pairs any number of times.

Return the lexicographically smallest string that s can be changed to after using the swaps.

Input: s = "dcab", pairs = [[0,3],[1,2]]
Output: "bacd"
Explaination: 
Swap s[0] and s[3], s = "bcad"
Swap s[1] and s[2], s = "bacd"

二、Solution

方法一:並查集

萬萬沒想到是並查集,一開始被無限制的交換嚇怕了,仔細想了想,不可能無限制地交換呀,啥時候結束也不知道,但我們能發現一個規律:

  • 在一個索引對內的兩個字符是可以任意交換地,也就是它們是在同一組的。
  • 其它索引對也是如此。
  • 但索引對與索引對之間的形成的各個字符組的相對位置是不變的,所以我們總能在進行交換各種索引對之間找到一種字典序最小的次序。
class Solution {
    int[] fa;
    int find(int x) {
        return x != fa[x] ? fa[x] = find(fa[x]) : x;
    }
    void uni(int x, int y) {
        int rx = find(x), ry = find(y);
        if (rx == ry) 
            return;
        fa[rx] = ry;
    }
    public String smallestStringWithSwaps(String s, List<List<Integer>> ps) {
        int n = s.length();
        fa = new int[n];
        for (int i = 0; i < n; i++) 
            fa[i] = i;
        for (List<Integer> p : ps)
            uni(p.get(0), p.get(1));
        
        Map<Integer, PriorityQueue<Character>> mp = new HashMap<>();
        for (int i = 0; i < n; i++) {
            mp.computeIfAbsent(find(i), v -> new PriorityQueue<>()).add(s.charAt(i));
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++)
            sb.append(mp.get(find(i)).poll());
            
        return sb.toString();
    }
}

複雜度分析

  • 時間複雜度:O(nlogn)O(nlogn)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章