https://leetcode.com/problems/minimum-number-of-moves-to-make-palindrome/
贪心,比较难想到
个人解答
class Solution:
def minMovesToMakePalindrome(self, s: str) -> int:
s = list(s)
res = 0
while s:
i = s.index(s[-1])
if i == len(s) - 1:
res += len(s) // 2
del s[-1]
else:
res += i
del s[i]
del s[-1]
return res
题目分析
就贪心就好,哎,想的太多了,没做出来。
看解答,其实就是对于每一个端点的值,找出另一端最靠近那端的index。
为什么这么可以呢?需要验证两个部分:
- 最短的更改,最终的端点一定是两端的其中一个
- 最短的更改,两遍选任意一个端点都可以
第一点,以a ... b
为例,如果a
/ b
作为端点,则匹配之后,可以剔除掉,不影响之后的交换。如果a
/b
匹配到中间,那么在之后的交换过程中,会经过匹配好的a
/b
,会多出两个swap。
最优情况下,不把a
/b
作为端点的swap数量和作为端点的swap数量相同,比如:acbacb
第二点,考虑一个通用的例子:a ... b ... a ... b
,第二个a
是最右边的a
,第一个b
是最左边的b
。那么想要匹配两者,必然会经历ab ... ba
这个过程:ab ... a ... b
-> ba ... a ... b
-> ba ... ab
<- **ab ... ba**
a ... b ... ab
-> a ... b ... ba
-> ab ... ba
<- **ab ... ba**
两者最后都需要同样的步数,因此选择哪个无所谓。
所以简单贪心就好了。
另外针对不能匹配的点,说明是最中心的,需要移动到中心。