leetcode_336_回文对

回文对

描述

困难

给定一组 互不相同 的单词, 找出所有不同的索引对(i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。

示例 1:

输入:["abcd","dcba","lls","s","sssll"]
输出:[[0,1],[1,0],[3,2],[2,4]] 
解释:可拼接成的回文串为 ["dcbaabcd","abcddcba","slls","llssssll"]

示例 2:

输入:["bat","tab","cat"]
输出:[[0,1],[1,0]] 
解释:可拼接成的回文串为 ["battab","tabbat"]

解题

首先是暴力做法,果然,超时了

class Solution:
    def palindromePairs(self, words: List[str]) -> List[List[int]]:
        res = []
        n = len(words)
        for i in range(n):
            for j in range(n):
                if i == j:
                    continue
                if self.is_palindrome(words[i] + words[j]):
                    res.append([i, j])
        return res

    def is_palindrome(self, s):
        right = len(s) - 1
        left = 0
        while left < right:
            if s[left] != s[right]:
                return False
            left += 1
            right -= 1
        return True

如果有两个字符串s1s2,他们拼接后有三种情况

  • len(s1) = len(s2),那么只需比较s1s2[::-1] 是否相同即可
  • len(s1) > len(s2)
    • s2 拼接在s1后面,那么s1的前len(s2)个字符等于s2[::-1],中间len(s2)len(s1) 个字符为回文串
      • 比如s1为"abc",s2为"ba",判断s1 前2个字符是否为s2 的逆序"ab",且s1剩余字符"c"是否为回文串
    • s2 拼接在s1前面,那么s1 的后len(s2) 个字符等于s2[::-1],s1的前len(s1)-len(s2) 个字符为回文串
      • 比如s1为"abc",s2为"cb",判断s1 后2个字符是否为s2 的逆序"bc",且s1剩余字符"a"是否为回文串
  • len(s1) < len(s2),将s1s2交换即变成上一种情况

算法

将所有字符串保存在字典中,键为该字符串,值为其下标

然后遍历每个字符串,可以看作为s1

并且将字符串分为 [:j][j:] 两部分

  • 如果第一部分的逆序存在于字典中,且第二部分为回文串,则为上面第二种情况的第一种情况
  • 如果第二部分的逆序存在于字典中,且第一部分为回文串,则为上面第二种情况的第二种情况

注意

在遍历时忽略上面第三种情况,默认为第一或二种情况

  • 可以通过 j 将字符串s1划分为 s1空字符串 "" ,此时为第一种情况
  • 分割后的子串和查找字典中是否存在该子串的逆序,则字典中的字符串长度要小于当前正在遍历的字符串,所以可以看做s2
class Solution:
    def palindromePairs(self, words: List[str]) -> List[List[int]]:
        res = []
        dic = {word: i for i, word in enumerate(words)}
        for i, word in enumerate(words):
            for j in range(len(word) + 1):
                temp1 = word[:j] 
                temp2 = word[j:]
                if temp1[::-1] in dic and dic[temp1[::-1]] != i and temp2 == temp2[::-1]:
                    res.append([i, dic[temp1[::-1]]])

                if j > 0 and temp2[::-1] in dic and dic[temp2[::-1]] != i and temp1 == temp1[::-1]:
                    res.append([dic[temp2[::-1]], i])
        return res