JoyAI LeetCode.336 回文对 public List<List<Integer>> palindromePairs(String[] words)

AI1周前发布 beixibaobao
9 0 0

给你一个字符串数组 words,要求找出所有不同的索引对 (i, j),使得 words[i] + words[j] 拼接后是一个回文串。

解题思路

关键在于枚举所有可能的拼接方式,并判断结果是否为回文。由于字符串长度和数量有限(最多5000个,每个最多300字符),我们可以用暴力+优化的方式解决。

核心思想:

  1. 对于每一对 (i, j),拼接 words[i] + words[j],判断是否为回文。
  2. 为了提升效率,可以预先对每个单词判断其是否为回文,以及它的反转是否在数组中。
  3. 优化点:利用“回文串的前缀/后缀”特性,避免重复拼接。

代码实现(Java)

import java.util.*;
public class Solution {
    public List<List<Integer>> palindromePairs(String[] words) {
        List<List<Integer>> result = new ArrayList<>();
        Map<String, Integer> wordToIndex = new HashMap<>();
        // 建立单词到索引的映射
        for (int i = 0; i < words.length; i++) {
            wordToIndex.put(words[i], i);
        }
        for (int i = 0; i < words.length; i++) {
            String word = words[i];
            String reversed = new StringBuilder(word).reverse().toString();
            // 情况1:word本身是回文,且存在空串,则 (i, j) 和 (j, i) 都合法
            if (word.isEmpty()) {
                for (int j = 0; j < words.length; j++) {
                    if (j != i && isPalindrome(words[j])) {
                        result.add(Arrays.asList(i, j));
                        result.add(Arrays.asList(j, i));
                    }
                }
                continue;
            }
            // 情况2:word的反转在数组中,且不是自己(避免重复)
            if (wordToIndex.containsKey(reversed) && wordToIndex.get(reversed) != i) {
                result.add(Arrays.asList(i, wordToIndex.get(reversed)));
            }
            // 情况3:word的前缀是回文,且后缀的反转在数组中
            for (int k = 1; k < word.length(); k++) {
                String prefix = word.substring(0, k);
                String suffix = word.substring(k);
                if (isPalindrome(prefix)) {
                    String suffixReversed = new StringBuilder(suffix).reverse().toString();
                    if (wordToIndex.containsKey(suffixReversed) && wordToIndex.get(suffixReversed) != i) {
                        result.add(Arrays.asList(wordToIndex.get(suffixReversed), i));
                    }
                }
            }
            // 情况4:word的后缀是回文,且前缀的反转在数组中
            for (int k = 0; k < word.length() - 1; k++) {
                String prefix = word.substring(0, k + 1);
                String suffix = word.substring(k + 1);
                if (isPalindrome(suffix)) {
                    String prefixReversed = new StringBuilder(prefix).reverse().toString();
                    if (wordToIndex.containsKey(prefixReversed) && wordToIndex.get(prefixReversed) != i) {
                        result.add(Arrays.asList(i, wordToIndex.get(prefixReversed)));
                    }
                }
            }
        }
        return result;
    }
    private boolean isPalindrome(String s) {
        int left = 0, right = s.length() - 1;
        while (left < right) {
            if (s.charAt(left) != s.charAt(right)) return false;
            left++;
            right--;
        }
        return true;
    }
}

复杂度分析

  • 时间复杂度:O(N × M²),其中 N 是单词数量,M 是平均单词长度。最坏情况下每个单词要检查所有前缀/后缀。
  • 空间复杂度:O(N × M),用于哈希表存储单词和索引。

示例

输入:["abcd","dcba","lls","s","sssll"]
输出:[[0,1],[1,0],[3,2],[2,4]]
解释:

  • "abcd" + "dcba" = "abcddcba" → 回文
  • "dcba" + "abcd" = "dcbaabcd" → 回文
  • "s" + "lls" = "slls" → 回文
  • "lls" + "sssll" = "llssssll" → 回文

这个解法覆盖了所有可能的回文拼接场景,适合 LeetCode 上的测试用例。

需要我帮你跑个样例或优化成 Python 版本吗?

© 版权声明

相关文章