LeetCode题解数据结构和算法分析

leetcode No336. Palindrome Pairs

2020-04-05  本文已影响0人  Dufre

Question

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:

Input: ["abcd","dcba","lls","s","sssll"]
Output: [[0,1],[1,0],[3,2],[2,4]] 
Explanation: The palindromes are ["dcbaabcd","abcddcba","slls","llssssll"]

Example 2:

Input: ["bat","tab","cat"]
Output: [[0,1],[1,0]] 
Explanation: The palindromes are ["battab","tabbat"]

Algorithm

暴力法我就不说了,暴力法时间复杂度为O(n×n×k),k为单词的平均长度。

下面来具体分析,先来看字符串s1(长度为k1),字符串s2(长度为k2)组合在一起判断是否是一个回文串有哪几种情况?

  1. k1 = k2
  2. k1 < k2
    s2剩下的部分必须要满足回文
  3. k1 > k2
    s1剩下的部分必须要满足回文


    三种情况

思考两个问题?

因此,需要构建的前缀树的结构如下:

class TrieNode {
    public TrieNode[] children;
    public int index;  //题目要求返回下标,因为这里记录下标
    public List<Integer> suffixs;  //记录节点向后所有的剩余能构成回文的字符串下标
    
    public TrieNode(){
        this.children = new TrieNode[26];
        this.index = -1;
        this.suffixs = new ArrayList<>();
    }
}

一个简单示例:

Code

class Solution {
    private TrieNode root;
    public boolean isPalindrome(String s){
        int i=0, j=s.length()-1;
        while (i < j){
            if (s.charAt(i) != s.charAt(j)){
                return false;
            }
            i++;
            j--;
        }

        return true;
    }
    public List<List<Integer>> palindromePairs(String[] words) {
        this.root = new TrieNode();
        int n = words.length;

        //build TrieNode Tree
        for (int i=0; i<n; i++){
            String word = new StringBuilder(words[i]).reverse().toString();
            TrieNode cur = root;

            if (isPalindrome(word.substring(0)))
                cur.suffixs.add(i);
            for (int j=0; j<word.length(); j++){
                int index = word.charAt(j) - 'a';
                if (cur.children[index] == null)
                    cur.children[index] = new TrieNode();
                cur = cur.children[index];
                if (isPalindrome(word.substring(j+1)))
                    cur.suffixs.add(i);
            }
            cur.index = i;
        }

        //search 
        List<List<Integer>> res = new ArrayList<>();
        for (int i=0; i<n; i++){
            String word = words[i];
            TrieNode cur = root;

            int j=0;
            for (; j<word.length(); j++){
                if (isPalindrome(word.substring(j)) && cur.index!=-1){
                    res.add(Arrays.asList(i, cur.index));
                }

                int index = word.charAt(j) - 'a';
                if (cur.children[index] == null)
                    break;
                cur = cur.children[index];
            }

            if (j == word.length()){
                for (int k : cur.suffixs){
                    if (k != i)
                        res.add(Arrays.asList(i, k));
                }
            }
        }

        return res;
    }
}

class TrieNode {
    public TrieNode[] children;
    public int index;
    public List<Integer> suffixs;
    
    public TrieNode(){
        this.children = new TrieNode[26];
        this.index = -1;
        this.suffixs = new ArrayList<>();
    }
}

时间复杂度:O(n×k×k),因为k在一定范围内,所以这个问题优化为一个线性问题。


时间复杂度

更多算法总结请关注我的微信公众号《Coder101》


Coder101
上一篇 下一篇

猜你喜欢

热点阅读