336 回文对(枚举)

1. 问题描述:

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

示例 1:

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

示例 2:

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

示例 3:

输入:words = ["a",""]
输出:[[0,1],[1,0]]

提示:
1 <= words.length <= 5000
0 <= words[i].length <= 300
words[i] 由小写英文字母组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-pairs

2. 思路分析:

① 当我们没有思路的时候可以根据题意画一下图发现其中的规律,由题目可知道两个单词能够拼成回文串有两种情况,如下图所示,第一个单词s1从开始到某个位置p对应的字符串是回文串,当第一个单词从p1到单词末尾位置对应的字符串与第二个单词互为逆序那么就可以拼成回文串,也即s2 + s1可以拼成回文串。第二种情况也是类似的,第一个单词从某个位置p到单词末尾是回文串,当第一个单词从开始位置到p位置对应的字符串与第二个单词互为逆序的时候说明是可以拼成回文串的,也即s1 + s2可以拼成回文串。

② 由①可知我们可以枚举每一个单词的分界点,根据①中的两种情况进行判断即可,这个需要注意的是当两个单词长度相等的时候需要特判一下,我们可以规定当判断第一种情况的时候判断了两个单词长度相等于不相等的两种情况所以当我们判断第二种情况的时候需要加多一个判断条件:只有当两个单词长度不等的满足条件的时候才将单词对应下标加入到结果中。可以结合["abcd", "dcba"]例子理解加入重复答案的过程(两个单词互为镜像的时候如果不添加限制条件会造成答案重复)。

3. 代码如下:

from typing import List
import collections


class Solution:
    # 判断是否是回文串
    def check(self, s: str):
        i, j = 0, len(s) - 1
        while i < j:
            if s[i] != s[j]: return False
            i += 1
            j -= 1
        return True

    def palindromePairs(self, words: List[str]) -> List[List[int]]:
        # 字典用来存储单词逆序
        dic = collections.defaultdict(int)
        for i in range(len(words)):
            w = words[i]
            dic[w[::-1]] = i
        res = list()
        # 例如例子 abcd 与dcba当截取空串的时候会判断两次那么加入的答案就是重复的所以第二个判断条件需要加上长度不相等的条件
        for i in range(len(words)):
            w = words[i]
            for j in range(len(w) + 1):
                left, right = w[0:j], w[j:]
                if self.check(right) and left in dic and dic[left] != i:
                    res.append([i, dic[left]])
                if self.check(left) and right in dic and dic[right] != i and len(w) != len(words[dic[right]]):
                    res.append([dic[right], i])
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值