力扣 leetcode 1202. 交換字串中的元素 (python)
技術標籤:pythonleetcode字串python演算法leetcode資料結構
Topic:
給你一個字串 s,以及該字串中的一些「索引對」陣列 pairs,其中 pairs[i] = [a, b] 表示字串中的兩個索引(編號從 0 開始)。
你可以 任意多次交換 在 pairs 中任意一對索引處的字元。
返回在經過若干次交換後,s 可以變成的按字典序最小的字串。
Example_1:
輸入:s = “dcab”, pairs = [[0,3],[1,2]]
輸出:“bacd”
解釋:
交換 s[0] 和 s[3], s = “bcad”
交換 s[1] 和 s[2], s = “bacd”
Example_2:
輸入:s = “dcab”, pairs = [[0,3],[1,2],[0,2]]
輸出:“abcd”
解釋:
交換 s[0] 和 s[3], s = “bcad”
交換 s[0] 和 s[2], s = “acbd”
交換 s[1] 和 s[2], s = “abcd”
Example_3:
輸入:s = “cba”, pairs = [[0,1],[1,2]]
輸出:“abc”
解釋:
交換 s[0] 和 s[1], s = “bca”
交換 s[1] 和 s[2], s = “bac”
交換 s[0] 和 s[1], s = “abc”
Solution:
本題整體思路基於
首先是建圖的過程:
將s中的值按照索引模擬成圖的n個節點
每個索引是一個節點
之後通過pairs中的陣列
將對應的可以互換的節點連通起來
之後是尋找聯通的所有節點用於儲存連通圖
將根節點相同的放在一起
以根節點作為鍵
值為陣列,儲存以該根節點為根的並查集中所有節點下標
最後分別對每個根節點對應的連通關係按照字典序進行單獨排列
將排序好的結果整合到res中即可完成
Code:
class UnionFind:
def __init__(self,s):
# 建立並查集圖
self.father = {i:i for i in range(len (s))}
def find(self,x):
# 查詢根節點
root = x
while self.father[root] != root:
root = self.father[root]
# 路徑壓縮
while x != root:
original_father = self.father[x]
self.father[x] = root
x = original_father
return root
def merge(self, x, y):
# 合併節點
root_x, root_y = self.find(x), self.find(y)
if root_x != root_y:
self.father[root_x] = root_y
class Solution:
def smallestStringWithSwaps(self, s: str, pairs: List[List[int]]) -> str:
# 建圖
uf = UnionFind(s)
for x, y in pairs:
uf.merge(x, y)
# 獲取聯通節點
connected = collections.defaultdict(list)
for node in range(len(s)):
connected[uf.find(node)].append(node)
# 重新賦值
res = list(s)
for nodes in connected.values():
last = nodes
string = sorted(res[d] for d in nodes)
for e, f in zip(last,string):
res[e] = f
return "".join(res)
Result: