交换字符串中的元素
难度:
标签:
题目描述
代码结果
运行时间: 145 ms, 内存: 39.3 MB
/*
* The idea is the same as the previous Java solution, using Union-Find to group connected indices.
* This version leverages Java Streams to perform some of the operations in a more functional style.
*/
import java.util.*;
import java.util.stream.Collectors;
public class SmallestStringWithSwapsStream {
public String smallestStringWithSwaps(String s, List<List<Integer>> pairs) {
int n = s.length();
UnionFind uf = new UnionFind(n);
// Union step for all pairs
pairs.forEach(pair -> uf.union(pair.get(0), pair.get(1)));
// Group all characters by root parent
Map<Integer, List<Character>> charGroups = new HashMap<>();
for (int i = 0; i < n; i++) {
int root = uf.find(i);
charGroups.computeIfAbsent(root, k -> new ArrayList<>()).add(s.charAt(i));
}
// Sort the characters in each group
charGroups.values().forEach(Collections::sort);
// Reconstruct the smallest string by replacing characters in sorted order
StringBuilder result = new StringBuilder(s);
Map<Integer, Iterator<Character>> groupIterators = charGroups.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().iterator()));
for (int i = 0; i < n; i++) {
int root = uf.find(i);
result.setCharAt(i, groupIterators.get(root).next());
}
return result.toString();
}
// Union-Find class
class UnionFind {
int[] parent;
int[] rank;
public UnionFind(int size) {
parent = new int[size];
rank = new int[size];
for (int i = 0; i < size; i++) {
parent[i] = i;
rank[i] = 1;
}
}
public int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
parent[rootY] = rootX;
rank[rootX] += 1;
}
}
}
}
}
解释
方法:
这个题解使用了并查集(Union-Find)数据结构来解决问题。首先,使用并查集将可以互相交换的字符分组。然后,将每个组内的字符按照字典序排序,以确保组内的字符排列是最小的。最后,重新构建字符串,确保每个位置的字符都是所在组内字典序最小的。
时间复杂度:
O(m + nlogn)
空间复杂度:
O(n)
代码细节讲解
🦆
在并查集中,如何处理具有多个连接组件的索引对,以确保所有相关索引都能正确合并?
▷🦆
为什么在处理每个组内的字符时选择对它们进行字典序排序,这种排序方式是否总是能保证最终结果是全局字典序最小?
▷🦆
并查集的`union`方法中,如果`root_x`等于`root_y`时直接返回,这种情况是否意味着已经处理过这对索引,会不会对最终结果造成影响?
▷🦆
在最终重构字符串时,为什么选择使用`pop()`方法从列表中取出字符,这种方式是否可能导致不稳定的字符选择,从而影响字典序的结果?
▷