Leetcode 1202. 交換字符串中的元素 (轉化爲聯通分量,獨立排序,思維比較獨特)

假設區間都是不相交的區間,此時區間彼此是獨立的,因此只需要兩兩交換看交換後字典序是否會變大,此時是典序的貪心思路。如果出現區間相交的情況,由於可以進行任意多次交換,那麼這組區域的字典序最小就是將他們排序。

因此思路是隻需要找到所有聯通區間,然後將其中對應字母排序,然後將排序後的結果插入到原來的字符串中,既可以得到重新組合後新生成的字符串。

 

統計區間的聯通性,使用到的數據結構是並查集。並查集處理完後,用一個HashMap數據結構來保存,每個根節點對應的字符串映射,我們遍歷一遍字符串,將這個字符映射建立起來。然後我們遍歷整個hashmap,對字符串排序,我們按照從大到小排序。這樣在遍歷一次字符串索引,找到其對應的根,在通過HashMap找到對應的字符串數組,然後取出最後一個,即爲這個位置要放的字符,最後就可以完成。

class DisjointSetUnion {
private:
    vector<int> p;
    int n;

public:
    DisjointSetUnion(int _n) {
        n = _n;
        p.resize(n);
        for (int i = 0; i < n; i++) {
            p[i] = i;
        }
    }

    int find(int x) {
        if(p[x]!=x) p[x] = find(p[x]);
        return p[x];
    }

    void unionSet(int x, int y) {
        p[find(x)] = find(y);
    }
};

class Solution {
public:
    string smallestStringWithSwaps(string s, vector<vector<int>>& pairs) {
        DisjointSetUnion dsu(s.length());
        for (auto& it : pairs) {
            dsu.unionSet(it[0], it[1]);
        }
        unordered_map<int, vector<int>> mp;
        for (int i = 0; i < s.length(); i++) {
            mp[dsu.find(i)].emplace_back(s[i]);
        }
        for (auto& [x, vec] : mp) {
            sort(vec.begin(), vec.end(), greater<int>());    
        }
        for (int i = 0; i < s.length(); i++) {
            int x = dsu.find(i);
            s[i] = mp[x].back();                             
            mp[x].pop_back();
        }
        return s;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章