Similarly to how we validate if a string is a palindrome, we turn the string into a palindrome starting with the two ends and converging towards the center. If the two ends do not match, we change one end into another, taking the cheaper of the two available options.
Time: , space:
.
class Solution:
def move(self, s: List[str], begin: int, nsteps: int, step: int) -> None:
while nsteps > 0:
next = begin+step
s[begin], s[next] = s[next], s[begin]
begin = next
nsteps -= 1
def find_first(self, target: str, s: List[str], begin: int, step: int) -> int:
while s[begin] != target:
begin += step
return begin
def minMovesToMakePalindrome(self, s: str) -> int:
char_list = list(s)
move_count = 0
left, right = 0, len(char_list)-1
while left < right:
p, q = char_list[left], char_list[right]
if p == q:
left += 1
right -= 1
continue
# pair looks like (p, q)
# How costly to turn p into q
q_index = self.find_first(q, char_list, left+1, 1)
q_distance = q_index - left
# How costly to turn q into p
p_index = self.find_first(p, char_list, right-1, -1)
p_distance = right - p_index
if q_distance <= p_distance:
move_count += q_distance
# p......q_index......q
self.move(char_list, q_index, q_distance, -1)
else:
move_count += p_distance
# p......p_index......q
self.move(char_list, p_index, p_distance, 1)
left += 1
right -= 1
return move_count
Leave a comment