# LeetCode algorithm problem 117 solution + joint search set

Posted by kennethl on Sun, 20 Feb 2022 20:15:38 +0100

## 1, Topic retelling

leetCode algorithm Title:
https://leetcode-cn.com/problems/H6lPxb/
Briefly described as:
1. Provides an array of strings. There are letter ectopic words between the string elements of the array. For example, "aaabb" and "baaab"; That is, the letters that make up the string are the same, and the letters appear the same number of times. The letter position can be different.
2. Define that two strings are similar: if a string can change into another string after exchanging the position of letters at most once, the two strings are similar. For example, "ab" and "ba"; "wbw" and "bww"; "stars" and "tsars";
3. Given a string list strs. Meet condition 1; How many similar string groups are there in strs?

## 2, Own solution

The first thought is to write a method to judge whether the two strings are similar. It is relatively simple and directly give the code:

```	@Test
public void test() {
System.out.println(isSimilarString("tars", "rats"));
System.out.println(isSimilarString("tars", "star"));
}

private boolean isSimilarString(String str1, String str2) {
if (str1.length() != str2.length()) {
return false;
}
List<Integer> diffIndexList = new ArrayList<>();
for (int i = 0; i < str1.length(); i++) {
if (str1.charAt(i) != str2.charAt(i)) {
if (diffIndexList.size() > 2) {
return false;
}
}
}
if (diffIndexList.size() == 0) {
return true;
}
if (diffIndexList.size() == 2) {
return str1.charAt(diffIndexList.get(0)) == str2.charAt(diffIndexList.get(1)) && str1.charAt(diffIndexList.get(1)) == str2.charAt(diffIndexList.get(0));
}
return false;
}
```

The following code gives you ideas first. You can try:
Traverse the string array. First, compare Str0 with Str1. If they are similar, put the two strings into one set. If they are not similar, the two strings are put into a set. Str2 is compared with the previous set in turn. If the elements of the set are similar to Str2, add Str2 to the existing set. Otherwise, Str2 creates its own set.

```public int numSimilarGroups(String[] strs) {
List<List<String>> group = new ArrayList<>();
for (int i = 0; i < strs.length; i++) {
String str = strs[i];
groupLoop:
for (List<String> list : group) {
for (String s : list) {
if (isSimilarString(s, str)) {
break groupLoop;
}
}
}
List<String> listObj = new ArrayList<>();
}
}
return group.size();
}
```

Then, after a simple test, it is submitted, and the result is reported as error. The error prompt cases are:

Think for A long time. When you don't have ideas, go back to read the question repeatedly and understand the question: "tars" and "rates" are similar (exchange the positions of 0 and 2); "rats" and "arts" are also similar, but "star" is not similar to "stars", which is simplified to A and B, B and C are similar, but A and C are not similar. This is different from the similarity in mathematics. Therefore, when traversing characters, it is possible that A, C, B, A and C are not similar. Two sets are created, but B is similar to A and B is similar to C. in this way, when traversing to B, the two sets of A and C need to be combined into A similar set. In fact, we can understand similarity as connectivity, which is in line with our thinking:

```	public int numSimilarGroups(String[] strs) {
List<List<String>> group = new ArrayList<>();
for (int i = 0; i < strs.length; i++) {
String str = strs[i];
List<Integer> similarListIndex = new ArrayList<>();
groupLoop:
for (int j = 0; j < group.size(); j++) {
List<String> list = group.get(j);
for (String s : list) {
if (isSimilarString(s, str)) {
break;
}
}
}
if (similarListIndex.isEmpty()) {
List<String> listObj = new ArrayList<>();
} else if(similarListIndex.size() == 1) {
} else {
List<String> mergeList = new ArrayList<>();
for (Integer listIndex : similarListIndex) {
}
int modify = 0;
for (int listIndex : similarListIndex) {
group.remove(listIndex - modify);
modify++;
}
}
}
return group.size();
}
```

Comprehensive submission Code: https://leetcode-cn.com/problems/H6lPxb/

## 3, Code learning - joint search set

After that, I looked at the official explanation. There was not much explanation. I read it for an hour and understood it a little. The explanation of the supplementary code is as follows. By the way, I also learned new knowledge - and search sets.
Someone else's code:

```class Solution {
public int numSimilarGroups(String[] strs) {
int n = strs.length;
int cnt = n;
// And the initialization of the search set. At the beginning, the father or ancestor of each element is itself.
int[] fathers = new int[n];
for(int i = 0; i < n; ++i){
fathers[i] = i;
}
// At first, the default grouping is equal to the length of the array, and each element is a group
// Traversal uses the method of combining numbers. Every two elements are combined once to judge whether they are similar.
for(int i = 0; i < n; ++i){
for(int j = i+1; j < n; ++j){
// The following elements are similar to the previous elements. The simple idea is that the two elements can be put into a group. The number of groups can be reduced by one. However:
// ***Difficulties***
// Then, judge whether similar elements have a common ancestor,
// If the ancestors are the same, for example, a is similar to B, a is the ancestor of B; A is similar to C, a is the ancestor of C; A has pulled B and C into a group. When traversing to B and C, the ancestors are all a, so there is no need to subtract one. The effect of their number of groups has been documented.
// If your ancestors are different, you can subtract one.
//Situation 1: primitive transformation, ancestors are themselves.
//Case 2: consolidation of different groups. For example, a is similar to B, a is not similar to C, and B is similar to C; B's ancestor is a and C's ancestor is C. It's different. Add C to the descendants of A. Reduce the number of groups by one.
if(isSimilar(strs[i], strs[j]) && union(fathers, i, j)){
cnt--;
}
}
}
return cnt;
}

public boolean isSimilar(String s1, String s2){
int cnt = 0;
for(int i = 0; i < s1.length(); ++i){
if(s1.charAt(i) != s2.charAt(i)) cnt++;
}
return cnt<=2;
}

public boolean union(int[] fathers, int i, int j){
int a = findFather(fathers, i);
int b = findFather(fathers, j);
if(a != b){
fathers[a] = b; // Where fathers[b] = a; It's OK. The characters are similar. Anyone can be an ancestor, as long as they remain unified and let the elements compared later be descendants.
return true;
}
return false;
}

public int findFather(int[] fathers, int i){
if(fathers[i] != i){
// Reference recursion solution.
fathers[i] = findFather(fathers, fathers[i]);
}
return fathers[i];
}
}

```

Author: SloanCheng
Source: LeetCode