生活随笔
收集整理的這篇文章主要介紹了
LeetCode 2157. 字符串分组(状态压缩+位运算+图的遍历)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
1. 題目
給你一個下標從 0 開始的字符串數組 words 。
每個字符串都只包含 小寫英文字母 。words 中任意一個子串中,每個字母都至多只出現一次。
如果通過以下操作之一,我們可以從 s1 的字母集合得到 s2 的字母集合,那么我們稱這兩個字符串為 關聯的 :
- 往 s1 的字母集合中添加一個字母。
- 從 s1 的字母集合中刪去一個字母。
- 將 s1 中的一個字母替換成另外任意一個字母(也可以替換為這個字母本身)。
數組 words 可以分為一個或者多個無交集的 組 。
一個字符串與一個組如果滿足以下 任一 條件,它就屬于這個組:
- 它與組內 至少 一個其他字符串關聯。
- 它是這個組中 唯一 的字符串。
注意,你需要確保分好組后,一個組內的任一字符串與其他組的字符串都不關聯。可以證明在這個條件下,分組方案是唯一的。
請你返回一個長度為 2 的數組 ans :
- ans[0] 是 words 分組后的 總組數 。
- ans[1] 是字符串數目最多的組所包含的字符串數目。
示例
1:
輸入:words
= ["a","b","ab","cde"]
輸出:
[2,3]
解釋:
- words
[0] 可以得到 words
[1] (將
'a' 替換為
'b')和 words
[2] (添加
'b')。所以 words
[0] 與 words
[1] 和 words
[2] 關聯。
- words
[1] 可以得到 words
[0] (將
'b' 替換為
'a')和 words
[2] (添加
'a')。所以 words
[1] 與 words
[0] 和 words
[2] 關聯。
- words
[2] 可以得到 words
[0] (刪去
'b')和 words
[1] (刪去
'a')。所以 words
[2] 與 words
[0] 和 words
[1] 關聯。
- words
[3] 與 words 中其他字符串都不關聯。
所以,words 可以分成
2 個組
["a","b","ab"] 和
["cde"] 。最大的組大小為
3 。示例
2:
輸入:words
= ["a","ab","abc"]
輸出:
[1,3]
解釋:
- words
[0] 與 words
[1] 關聯。
- words
[1] 與 words
[0] 和 words
[2] 關聯。
- words
[2] 與 words
[1] 關聯。
由于所有字符串與其他字符串都關聯,所以它們全部在同一個組內。
所以最大的組大小為
3 。提示:
1 <= words
.length
<= 2 * 10^4
1 <= words
[i
].length
<= 26
words
[i
] 只包含小寫英文字母。
words
[i
] 中每個字母最多只出現一次。
來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/groups-of-strings
著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。
2. 解題
- 把單詞26個字符是否出現作為 int 數的一個 bit 的 01 ,把字符串轉成數字,并記錄個數(有重復的字符串)
- 枚舉 每個數字的 26 個位,使用題目給的3中規則進行變形,得到其他的數字,如果數字出現過,則這兩個數字節點有一條無向邊,構建圖
- 圖的遍歷,找到連通塊的數量,最大連通塊的節點個數
class Solution {
public:vector
<int> groupStrings(vector
<string
>& words
) {unordered_map
<int, unordered_set
<int>> g
;unordered_set
<int> node
;unordered_map
<int, int> node_ct
;for(auto& w
: words
){int num
= 0;for(auto c
: w
)num
|= 1<<(c
-'a'); node
.insert(num
); node_ct
[num
]++; }for(auto num
: node
){for(int i
= 0; i
< 26; ++i
){ if((num
>>i
)&1) {int othernum
= num
& ~(1<<i
); if(node
.find(othernum
) != node
.end()){g
[num
].insert(othernum
);g
[othernum
].insert(num
);}for(int j
= 0; j
< 26; ++j
){ if(i
==j
|| ((othernum
>>j
)&1)==1) continue;int anothernum
= othernum
| (1<<j
);if(node
.find(anothernum
) != node
.end()){g
[num
].insert(anothernum
);g
[anothernum
].insert(num
);}}}else {int othernum
= num
| (1<<i
); if(node
.find(othernum
) != node
.end()){g
[num
].insert(othernum
);g
[othernum
].insert(num
);}}}}unordered_set
<int> vis
; int group
= 0, ct
= 0, maxct
= 0;for(auto num
: node
){if(vis
.find(num
) != vis
.end()) continue;group
++;queue
<int> q
;q
.push(num
);vis
.insert(num
);ct
= 0;while(!q
.empty()){int tp
= q
.front();ct
+= node_ct
[tp
];q
.pop();for(auto nt
: g
[tp
]){if(vis
.find(nt
) != vis
.end()) continue;q
.push(nt
);vis
.insert(nt
);}}maxct
= max(maxct
, ct
);}return {group
, maxct
};}
};
1276 ms 199.5 MB C++
我的CSDN博客地址 https://michael.blog.csdn.net/
長按或掃碼關注我的公眾號(Michael阿明),一起加油、一起學習進步!
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的LeetCode 2157. 字符串分组(状态压缩+位运算+图的遍历)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。