Given a string s, no longer than 4,000 characters, and a list pairs of pairs of indices in the string (0-indexed), determine the lexicographically smallest string that can be obtained by swapping the characters at the indices in the given pairs any number of times.
i can be swapped with j, and j with k, then effectively i can be swapped with k.class UnionFind:
def __init__(self, size):
self.root = list(range(size))
self.rank = [1] * size
def find(self, x):
if x != self.root[x]:
self.root[x] = self.find(self.root[x])
return self.root[x]
def union(self, x, y):
rootX = self.find(x)
rootY = self.find(y)
if rootX != rootY:
if self.rank[rootX] > self.rank[rootY]:
self.root[rootY] = rootX
elif self.rank[rootX] < self.rank[rootY]:
self.root[rootX] = rootY
else:
self.root[rootY] = rootX
self.rank[rootX] += 1
def smallestStringWithSwaps(s, pairs):
n = len(s)
union_find = UnionFind(n)
for x, y in pairs:
union_find.union(x, y)
root_to_component = {}
for i in range(n):
root = union_find.find(i)
if root not in root_to_component:
root_to_component[root] = []
root_to_component[root].append(i)
smallest_string = list(s)
for component in root_to_component.values():
chars = [s[i] for i in component]
chars.sort()
for i, char in zip(sorted(component), chars):
smallest_string[i] = char
return ''.join(smallest_string)
# Example usage:
s = "dcab"
pairs = [[0, 3], [1, 2]]
print(smallestStringWithSwaps(s, pairs)) # Output: "bacd"
O(α(N)) time, where α is the inverse Ackermann function, which is very small (almost constant time). Hence, for N operations, it’s effectively O(N).O(N log N), where N is the length of the string.Overall, the time complexity is O(N log N) due to the sorting operation.
Got blindsided by a question you didn’t expect?
Spend too much time studying?
Or simply don’t have the time to go over all 3000 questions?