839.同様の文字列グループ
文字列X
など、2つの異なる位置にある文字の交換文字列Y
が等しい場合、いわゆるX
、とY
2つの類似した文字列。2つの文字列自体が等しい場合、それらも類似しています。
たとえば、"tars"
および"rats"
類似(交換0
および2
位置);"rats"
および"arts"
類似しているが、"star"
そうではない"tars"
、"rats"
または"arts"
類似。
要するに、それらは類似性を通じて2つの関連グループを形成{"tars", "rats", "arts"}
し{"star"}
ます:と。"tars"
と"arts"
は、類似していなくても同じグループに属していることに注意してください。正式には、各グループについて、グループ内の単語を決定するために、それはグループ内の少なくとも1つの単語に類似している必要があるだけです。
文字列のリストを提供しますstrs
。各文字列は、strs
異所性のすべての文字列という単語の他の文字のリストです。strs
同様のグループの文字列をどれだけ尋ねますか?
例1:
输入:strs = ["tars","rats","arts","star"]
输出:2
例2:
输入:strs = ["omv","ovm"]
输出:1
促す:
- 1 <= strs.length <= 100
- 1 <= strs [i] .length <= 1000
- sum(strs [i] .length)<= 2 * 104
- strs [i]には小文字のみが含まれます。
- strsのすべての単語は同じ長さであり、互いに透けて見える単語です。
備考:
- アナグラムは、文字列の文字の位置(順序)を変更することによって形成される新しい単語です。
方法1:収集して確認する
問題解決のアイデア
もちろん、1月の最終日は「コンバインドチェックコレクション」で終わる必要があります〜
特別な解決策はありません。2層ループは、2つの文字列が「類似した文字列」であるかどうかを正直に比較します。文字列がunion
一緒に缶に似ている場合。
参照コード
public int numSimilarGroups(String[] strs) {
int n = strs.length;
UnionFind unionFind = new UnionFind(n);
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (unionFind.connected(i, j)) {
continue;
}
if (isSimilar(strs[i], strs[j])) {
unionFind.union(i, j);
}
}
}
return unionFind.getCount();
}
// 判断两个字符串是否为“相似字符串”
public boolean isSimilar(String s1, String s2) {
char[] cs1 = s1.toCharArray(), cs2 = s2.toCharArray();
int num = 0;
for (int i = 0; i < cs1.length; i++) {
if (cs1[i] != cs2[i]) {
num++;
if (num > 2) {
return false;
}
}
}
return true;
}
// 并查集模板
class UnionFind {
private int[] parent;
private int count;
public UnionFind(int n) {
count = n;
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
public void union(int x, int y) {
int rootX = find(x), rootY = find(y);
if (rootX == rootY) {
return;
}
parent[rootX] = rootY;
count--;
}
public int find(int x) {
return parent[x] == x ? parent[x] : (parent[x] = find(parent[x]));
}
public boolean connected(int x, int y) {
return find(x) == find(y);
}
public int getCount() {
return count;
}
}
の結果