1. 程式人生 > 其它 >【leetcode】839. 相似字串組(similar-string-groups)(並查集)[困難]

【leetcode】839. 相似字串組(similar-string-groups)(並查集)[困難]

技術標籤:leetcode題解leetcode並查集

連結

https://leetcode-cn.com/problems/similar-string-groups/

耗時

解題:26 min
題解:12 min

題意

如果交換字串 X 中的兩個不同位置的字母,使得它和字串 Y 相等,那麼稱 X 和 Y 兩個字串相似。如果這兩個字串本身是相等的,那它們也是相似的。

例如,“tars” 和 “rats” 是相似的 (交換 0 與 2 的位置); “rats” 和 “arts” 也是相似的,但是 “star” 不與 “tars”,“rats”,或 “arts” 相似。

總之,它們通過相似性形成了兩個關聯組:{“tars”, “rats”, “arts”} 和 {“star”}。注意,“tars” 和 “arts” 是在同一組中,即使它們並不相似。形式上,對每個組而言,要確定一個單詞在組中,只需要這個詞和該組中至少一個單詞相似。

給你一個字串列表 strs。列表中的每個字串都是 strs 中其它所有字串的一個字母異位詞。請問 strs 中有多少個相似字串組?

提示:

  • 1 <= strs.length <= 100
  • 1 <= strs[i].length <= 1000
  • sum(strs[i].length) <= 2 * 104
  • strs[i] 只包含小寫字母。
  • strs 中的所有單詞都具有相同的長度,且是彼此的字母異位詞。

備註: 字母異位詞(anagram),一種把某個字串的字母的位置(順序)加以改換所形成的新詞。

思路

比較暴力的一個想法,對於每個字串遍歷字串列表中所有字串找與其相似的字串(即兩個字串中只有兩個字元不同或沒有字元不同)。使用並查集統計相似字串組的數量,初始時設定相似字串組的數量為字串列表的長度,合併所有相似字串,最終並查集中集合的數量即是答案(strs中相似字串組的數量)。

時間複雜度: O ( s u m ( s t r s [ i ] . l e n g t h ) ∗ s t r s . l e n g t h ) = O ( 1 0 6 ) O(sum(strs[i].length)*strs.length)=O(10^6) O(sum(strs[i].length)strs.length)=O(106)

AC程式碼

class Solution {
public:
    constexpr static int MAXN = 110;
    int father[MAXN];   //  儲存i的father父節點  
    int setcnt = 1;
void makeSet() { for (int i = 0; i < MAXN; i++) father[i] = i; } int findRoot(int x) { // 迭代找根節點 int root = x; // 根節點 while (root != father[root]) { // 尋找根節點 root = father[root]; } while (x != root) { int tmp = father[x]; father[x] = root; // 根節點賦值 x = tmp; } return root; } void Union(int x, int y) { // 將x所在的集合和y所在的集合整合起來形成一個集合。 int a, b; a = findRoot(x); b = findRoot(y); if(a == b) return ; father[a] = b; // y連在x的根節點上 或father[b] = a為x連在y的根節點上 setcnt--; } int numSimilarGroups(vector<string>& strs) { int n = strs.size(); setcnt = n; makeSet(); for(int i = 0; i < n; ++i) { for(int j = i+1; j < n; ++j) { string stra = strs[i]; string strb = strs[j]; int diffnum = 0; for(int k = 0; k < stra.size(); ++k) { if(stra[k] != strb[k]) { diffnum++; if(diffnum > 2) { break; } } } if(diffnum == 0 || diffnum == 2) { Union(i, j); } } } return setcnt; } };