For example, given the equivalency information from s1 = "abc" and s2 = "cde", "acd" and "aab" are equivalent strings of baseStr = "eed", and "aab" is the lexicographically smallest equivalent string of baseStr.
Return the lexicographically smallest equivalent string ofbaseStrby using the equivalency information froms1ands2.
Input:
s1 ="parker", s2 ="morris", baseStr ="parser"Output:
"makkek"Explanation: Based on the equivalency information in s1 and s2, we can group their characters as [m,p],[a,o],[k,r,s],[e,i].The characters in each group are equivalent and sorted in lexicographical order.So the answer is"makkek".
Example 2:
1
2
3
4
5
6
Input:
s1 ="hello", s2 ="world", baseStr ="hold"Output:
"hdld"Explanation: Based on the equivalency information in s1 and s2, we can group their characters as [h,w],[d,e,o],[l,r].So only the second letter 'o'in baseStr is changed to 'd', the answer is"hdld".
Example 3:
1
2
3
4
5
Input:
s1 ="leetcode", s2 ="programs", baseStr ="sourcecode"Output:
"aauaaaaada"Explanation: We group the equivalent characters in s1 and s2 as [a,o,e,r,s,c],[l,p],[g,t] and [d,m], thus all letters in baseStr except 'u' and 'd' are transformed to 'a', the answer is"aauaaaaada".
The key idea is to use union-find to group all equivalent characters. For each character, its representative in the union-find structure is the lexicographically smallest character in its equivalence class. For each character in baseStr, replace it with the smallest equivalent character.
classSolution {
public: string smallestEquivalentString(string s1, string s2, string baseStr) {
vector<int> par(26);
iota(par.begin(), par.end(), 0);
auto find = [&](int x) {
while (par[x] != x) x = par[x] = par[par[x]];
return x;
};
for (int i =0; i < s1.size(); ++i) {
int a = find(s1[i] -'a'), b = find(s2[i] -'a');
if (a != b) par[max(a, b)] = min(a, b);
}
string ans;
for (char c : baseStr) ans += (char)(find(c -'a') +'a');
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
funcsmallestEquivalentString(s1, s2, baseStrstring) string {
par:= make([]int, 26)
fori:=rangepar { par[i] = i }
varfindfunc(int) intfind = func(xint) int { ifpar[x] !=x { par[x] = find(par[x]) }; returnpar[x] }
fori:=0; i < len(s1); i++ {
a, b:=find(int(s1[i]-'a')), find(int(s2[i]-'a'))
ifa!=b {
ifa < b { par[b] = a } else { par[a] = b }
}
}
ans:= make([]byte, len(baseStr))
fori:=0; i < len(baseStr); i++ {
ans[i] = byte(find(int(baseStr[i]-'a')) +'a')
}
return string(ans)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classSolution {
public String smallestEquivalentString(String s1, String s2, String baseStr) {
int[] par =newint[26];
for (int i = 0; i < 26; i++) par[i]= i;
for (int i = 0; i < s1.length(); i++) {
int a = find(par, s1.charAt(i) -'a');
int b = find(par, s2.charAt(i) -'a');
if (a != b) par[Math.max(a, b)]= Math.min(a, b);
}
StringBuilder ans =new StringBuilder();
for (char c : baseStr.toCharArray()) ans.append((char)(find(par, c -'a') +'a'));
return ans.toString();
}
privateintfind(int[] par, int x) {
if (par[x]!= x) par[x]= find(par, par[x]);
return par[x];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
classSolution {
funsmallestEquivalentString(s1: String, s2: String, baseStr: String): String {
val par = IntArray(26) { it }
funfind(x: Int): Int = if (par[x] == x) x else { par[x] = find(par[x]); par[x] }
for (i in s1.indices) {
val a = find(s1[i] - 'a')
val b = find(s2[i] - 'a')
if (a != b) par[maxOf(a, b)] = minOf(a, b)
}
return baseStr.map { (find(it - 'a') + 'a'.code).toChar() }.joinToString("")
}
}
1
2
3
4
5
6
7
8
9
10
11
12
classSolution:
defsmallestEquivalentString(self, s1: str, s2: str, baseStr: str) -> str:
par = list(range(26))
deffind(x: int) -> int:
if par[x] != x:
par[x] = find(par[x])
return par[x]
for a, b in zip(s1, s2):
pa, pb = find(ord(a)-97), find(ord(b)-97)
if pa != pb:
par[max(pa, pb)] = min(pa, pb)
return''.join(chr(find(ord(c)-97)+97) for c in baseStr)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
impl Solution {
pubfnsmallest_equivalent_string(s1: String, s2: String, base_str: String) -> String {
letmut par: Vec<_>= (0..26).collect();
fnfind(par: &mut Vec<usize>, x: usize) -> usize {
if par[x] != x { par[x] = find(par, par[x]); }
par[x]
}
let s1 = s1.as_bytes();
let s2 = s2.as_bytes();
for i in0..s1.len() {
let a = find(&mut par, (s1[i] -b'a') asusize);
let b = find(&mut par, (s2[i] -b'a') asusize);
if a != b {
par[a.max(b)] = a.min(b);
}
}
base_str.bytes().map(|c| (find(&mut par, (c -b'a') asusize) asu8+b'a') aschar).collect()
}
}