336. Palindrome Pairs

本文介绍了一种寻找字符串数组中所有能组成回文串的唯一字符串对的方法。通过逆序匹配,该算法能够高效地找到所有符合条件的字符串组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a list of unique words, find all pairs of distinct indices (i, j) in the given list, so that the concatenation of the two words, i.e. words[i] + words[j] is a palindrome.

Example 1:
Given words = ["bat", "tab", "cat"]
Return [[0, 1], [1, 0]]
The palindromes are ["battab", "tabbat"]

Example 2:
Given words = ["abcd", "dcba", "lls", "s", "sssll"]
Return [[0, 1], [1, 0], [3, 2], [2, 4]]
The palindromes are ["dcbaabcd", "abcddcba", "slls", "llssssll"]

Credits:

Special thanks to @dietpepsi for adding this problem and creating all test cases.



The idea is for each of the word, find the strings that can be added before or after to form a palindrome, and generate the results.

For example "abcd"

before abcd we could add dcba to form dcbaabcd,

and add dcb to form dcbabcd.

after abcd we could add dcba to form abcddcba

and add cba to form abcdcba.

And we check whether dcba,dcb,dcba,cba is in the list, if there is a occurence we add (i,j) or (j,i) to the result.


But there would be duplicates if abcd and dcba all the in the list, because for after abcd we will find dcba, and for before dcba we will find abcd.

what we could do is in whether the getBefore or getAfter, we do not return the reverse of the string s to avoid the duplicates.


Code:

public class Solution {
    public List<List<Integer>> palindromePairs(String[] words) {
        List<List<Integer>> ret = new ArrayList<>();
        HashMap<String,HashSet<Integer>> hm = new HashMap<>();
        for(int i = 0; i < words.length; i++){
            hm.computeIfAbsent(words[i], k->new HashSet<Integer>()).add(i);
        }
        
        for(int i = 0; i < words.length; i++){
            String s = words[i];
            List<String> before = getBefore(s);
            List<String> after = getAfter(s);
            
            for(String bf : before){
                for(int j : hm.getOrDefault(bf,new HashSet<Integer>())){
                    List<Integer> temp = new ArrayList<>();
                    if(i == j) continue;
                    temp.add(j);
                    temp.add(i);
                    ret.add(temp);
                    
                }
            }
            
            for(String af : after){
                for(int j : hm.getOrDefault(af,new HashSet<Integer>())){
                    List<Integer> temp = new ArrayList<>();
                    if(i == j) continue;
                    temp.add(i);
                    temp.add(j);
                    ret.add(temp);
                }
            }
        }

        return ret;
    }
    
    public List<String> getAfter(String s){
        List<String> ret = new ArrayList<>();
        String rev = new StringBuilder(s).reverse().toString();
        for(int i = 0; i <= s.length(); i++){
            if(rev.substring(0,i).equals(s.substring(s.length() - i,s.length()))){
                ret.add(rev.substring(i,s.length()));
            }
        }
        return ret;
    }
    
    public List<String> getBefore(String s){
        List<String> ret = new ArrayList<>();
        String rev = new StringBuilder(s).reverse().toString();
        for(int i = 1; i <= s.length(); i++){ // i start from 1 to avoid duplicates
            if(s.substring(0,i).equals(rev.substring(s.length() - i,s.length()))){
                ret.add(rev.substring(0,s.length() - i));
            }
        }
        return ret;
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值