05 August 2008
给定一个字符串 s,以及字符串对中的索引对数组,其中对 [i] = [a, b] 表示字符串的 2 个索引(0 索引)。
可以多次交换给定对中任何一对索引处的字符。
返回使用交换后 s 可以更改为的字典最小字符串。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Example 1:
Input: s = "dcab", pairs = [[0,3],[1,2]]
Output: "bacd"
Explaination:
Swap s[0] and s[3], s = "bcad"
Swap s[1] and s[2], s = "bacd"
Example 2:
Input: s = "dcab", pairs = [[0,3],[1,2],[0,2]]
Output: "abcd"
Explaination:
Swap s[0] and s[3], s = "bcad"
Swap s[0] and s[2], s = "acbd"
Swap s[1] and s[2], s = "abcd"
Example 3:
Input: s = "cba", pairs = [[0,1],[1,2]]
Output: "abc"
Explaination:
Swap s[0] and s[1], s = "bca"
Swap s[1] and s[2], s = "bac"
Swap s[0] and s[1], s = "abc"
Union Find + HashMap + PriorityQueue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class Solution {
public String smallestStringWithSwaps(String s, List<List<Integer>> pairs) {
if (pairs.size() == 0) {
return s;
}
int len = s.length();
UnionFind unionFind = new UnionFind(len);
for (List<Integer> pair : pairs) {
int index1 = pair.get(0);
int index2 = pair.get(1);
unionFind.union(index1, index2);
}
char[] charArray = s.toCharArray();
Map<Integer, PriorityQueue<Character>> hashMap = new HashMap<>(len);
for (int i = 0; i < len; i++) {
int root = unionFind.find(i);
if (hashMap.containsKey(root)) {
hashMap.get(root).offer(charArray[i]);
} else {
PriorityQueue<Character> minHeap = new PriorityQueue<>();
minHeap.offer(charArray[i]);
hashMap.put(root, minHeap);
}
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < len; i++) {
int root = unionFind.find(i);
stringBuilder.append(hashMap.get(root).poll());
}
return stringBuilder.toString();
}
private class UnionFind {
private int[] parent;
private int[] rank;
public UnionFind(int n) {
this.parent = new int[n];
this.rank = new int[n];
for (int i = 0; i < n; i++) {
this.parent[i] = i;
this.rank[i] = 1;
}
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY) {
return;
}
if (rank[rootX] == rank[rootY]) {
parent[rootX] = rootY;
rank[rootY]++;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
parent[rootY] = rootX;
}
}
public int find(int x) {
if (x == parent[x])
return x;
return parent[x] = find(parent[x]);
}
}
}
Union Find + HashMap + Sort
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
class Solution {
public class UnionFind {
private int[] roots;
private int[] ranks;
private int group;
public UnionFind(int n) {
roots = new int[n];
ranks = new int[n];
group = n;
for(int i = 0; i < n; ++i) {
roots[i] = i;
ranks[i] = 1;
}
}
public int find(int x) {
if(x == roots[x])
return x;
return roots[x] = find(roots[x]);
}
public boolean union(int x, int y) {
int rootx = find(x);
int rooty = find(y);
if(rootx != rooty) {
if(ranks[rootx] > ranks[rooty]) {
roots[rooty] = rootx;
} else if(ranks[rootx] < ranks[rooty]) {
roots[rootx] = rooty;
} else {
roots[rooty] = rootx;
ranks[rootx] += 1;
}
group--;
return true;
}
return false;
}
public int getGroup() {
return group;
}
}
public String smallestStringWithSwaps(String s, List<List<Integer>> pairs) {
// group indices by union find
int slen = s.length();
UnionFind uf = new UnionFind(slen);
for(List<Integer> pair : pairs) {
uf.union(pair.get(0), pair.get(1));
}
// get indices of each group
Map<Integer, List<Integer>> map = new HashMap<>();
for(int i = 0; i < slen; ++i) {
int root = uf.find(i);
if(!map.containsKey(root))
map.put(root, new ArrayList<>());
map.get(root).add(i);
}
// get characters by the indices of each group, sort by the characters,
// then put the sorted characters back to new characters array by the indices.
char[] newChars = new char[slen];
for(Map.Entry<Integer, List<Integer>> e : map.entrySet()) {
List<Integer> group = e.getValue();
int glen = group.size();
char[] gchars = new char[glen];
for(int i = 0; i < glen; ++i)
gchars[i] = s.charAt(group.get(i));
Arrays.sort(gchars);
for(int i = 0; i < glen; ++i)
newChars[group.get(i)] = gchars[i];
}
return new String(newChars);
}
}