|
|
第四题:- # Follow up of LC 1153. String transforms into another string
- # return min number of transformation
- def MinNumSteps(str1, str2):
- '''
- build the graph of transformation
-
- several facts of the graph:
- + three types of connected component
- 1) a long chain
- 2) a chain with with cycle at the end
- 3) a cycle
- + only can enter a cycle, cannot go out
- + one connected componnet only one cycle
-
- to transform a cycle:
- + if type 3), then number of transformation
- = cycle length + 1 (additional one is to
- break the cycle)
- + if type 2), = cycle length
- example: abcd -> bcaa
- graph: d -> a -> b -> c -> a
- break cycle by change c to d first
- '''
-
- if str1 == str2: return 0
-
- # build graph and check feasibility
- mapping = {}
- indegree = {}
- unique_char_in_str2 = set()
- for char1, char2 in zip(str1, str2):
- unique_char_in_str2.add(str2)
- if char1 != char2:
- if char1 in mapping and mapping[char1] != char2:
- return -1
- mapping[char1] = char2
- indegree[char2] = indegree.get(char2, 0) + 1
- if len(unique_char_in_str2) == 26:
- return -1
-
- def dfs(char):
- start = char
- total_length = 0
- while char in visited and visited[char] == 0:
- if char in mapping:
- total_length += 1
- visited[char] = 1
- char = mapping.get(char, None)
-
- if char in visited and visited[char] == 1:
- # cycle found
- cycle_length = 0
- # if there is a char with indegree > 1
- # we can always change the char in the
- # cycle to one of the other char that
- # point to that char
- # example: abcd -> bcaa
- # graph: d -> a -> b -> c -> a
- # a has indegree=2, we can change
- # c to d first; by doing this, we can
- # break the cycle without any extra steps
- has_outside_nodes = False
- while visited[char] == 1:
- if indegree[char] > 1:
- has_outside_nodes = True
- visited[char] = 2
- cycle_length += 1
- char = mapping[char]
- if has_outside_nodes:
- total_length = cycle_length
- total_length = cycle_length + 1
-
- # go thru the chain again and mark all as visited
- char = start
- while char in visited and visited[char] == 1:
- visited[char] = 2
- char = mapping.get(char, None)
- return total_length
-
- # now graph is ready and we know we can transform
- num_steps = 0
- visited = {char: 0 for char in mapping}
-
- for char in mapping:
- if visited[char] == 0:
- num_steps += dfs(char)
-
- return num_steps
复制代码 |
|