336. Palindrome Pairs

Leetcode: 336.Palindrome Pairs
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"]

Strategy:
  1. List of words, needs one layer of looping
  2. Number of letters in a word is not fixed, needs deep lool into each word, another layer of looping
  3. The order of compositing a pair, (a, b) or (b, a), needs to be separated as two times
  4. When looping, the front part is starting from index 0, and the second part must be ending with the index of length of letters
  5. Either the front or the second part could be searched in the list of words, and the other part should be tested for palindorme
New Solution:
class Solution {
    static class Trie{
        TrieNode root;
        final static int AlphabetSize = 26;
        Trie(){
            root = new TrieNode(-1);
        }
        public void add(String word, int id){
            TrieNode head = root;
            for(int i = word.length()-1;i>=0; i--){
                int j = word.charAt(i) -'a';
                if(head.dsc[j] == null){
                    head.dsc[j] = new TrieNode(-1);
                }
                if(isPalindrome(word,0,i)) 
                    head.indices.add(id);//can cover "" string cases. e.g. for string "aaa",root will have its index
                head = head.dsc[j];
            }
            head.indices.add(id);
            head.idx = id;
        }
        public void search(String word,int id, List<List<Integer>> rs){
            TrieNode head = root;
            for(int i=0; i< word.length(); i++){
                if(head.idx!=-1 && isPalindrome(word,i,word.length()-1))
                    rs.add(Arrays.asList(id,head.idx));
                int j = word.charAt(i) - 'a';
                if(head.dsc[j] == null)
                    return ;
                head = head.dsc[j];
            }
            for(int a : head.indices){
                if(a!=id)
                    rs.add(Arrays.asList(id,a));
            }
        }
        private boolean isPalindrome(String str1, int i, int j){
            while(i<=j){
                if(str1.charAt(i++)!=str1.charAt(j--)){
                    return false;
                }   
            }
            return true;
        }
        static class TrieNode{
            int idx; // -1 means no words ends at this node. i means words[i] ends here
            TrieNode[] dsc;
            List<Integer> indices;// indices passing through this node 
            TrieNode(int idx){
                this.idx = idx;
                dsc = new TrieNode[AlphabetSize];
                indices = new LinkedList<>();
            }
        }
    }
    public List<List<Integer>> palindromePairs(String[] words) {
        List<List<Integer>> rs = new LinkedList<>();
        Trie dict = new Trie();
        for(int i =0; i< words.length; i++) 
            dict.add(words[i],i);
        for(int i = 0; i<words.length; i++)
            dict.search(words[i],i,rs);
        return rs;
    }
}
My Final Solution:
public class Solution {
    public List<List<Integer>> palindromePairs(String[] words) {
        List<List<Integer>> pairs = new ArrayList<List<Integer>>();
        if(words == null || words.length == 0) return pairs;
        HashMap<String, Integer> map = new HashMap<>();
        for(int i = 0; i < words.length; i++) map.put(words[i], i);
        for(int i = 0; i < words.length; i++){
            for(int j = 0; j <= words[i].length(); j++){ // <= not <
                String frontStr = words[i].substring(0, j);
                String backStr = words[i].substring(j);
                
                if(isPalindrome(frontStr)){
                    String backRev = new StringBuilder(backStr).reverse().toString();
                    if(map.containsKey(backRev) && map.get(backRev) != i){
                        pairs.add(Arrays.asList(new Integer[]{map.get(backRev), i}));
                    }
                } 
                if(isPalindrome(backStr) && backStr.length() != 0){ //exam the length for backString is 0 or not
                    String frontRev = new StringBuilder(frontStr).reverse().toString();
                    if(map.containsKey(frontRev) && map.get(frontRev) != i){
                        pairs.add(Arrays.asList(new Integer[]{i,map.get(frontRev)}));
                    }
                }
            }
        }
        return pairs;
    }
    
    private boolean isPalindrome(String s) {
        for (int i = 0; i < s.length()/2; ++ i) // half of length
            if (s.charAt(i) != s.charAt(s.length()-1-i))
                return false;
        return true;
    }
}
Referenced Solutions:
public class Solution {
    public List<List<Integer>> palindromePairs(String[] words) {
        List<List<Integer>> pairs = new LinkedList<>();
        if (words == null) return pairs;
        HashMap<String, Integer> map = new HashMap<>();
        for (int i = 0; i < words.length; ++ i) map.put(words[i], i);
        for (int i = 0; i < words.length; ++ i) {
            int l = 0, r = 0;
            while (l <= r) {
                String s = words[i].substring(l, r);
                Integer j = map.get(new StringBuilder(s).reverse().toString());
                if (j != null && i != j && isPalindrome(words[i].substring(l == 0 ? r : 0, l == 0 ? words[i].length() : l)))
                    pairs.add(Arrays.asList(l == 0 ? new Integer[]{i, j} : new Integer[]{j, i}));
                if (r < words[i].length()) ++r;
                else ++l;
            }
        }
        return pairs;
    }
    
    private boolean isPalindrome(String s) {
        for (int i = 0; i < s.length()/2; ++ i)
            if (s.charAt(i) != s.charAt(s.length()-1-i))
                return false;
        return true;
    }
}
class Solution {
    public List<List<Integer>> palindromePairs(String[] words) {
        List<List<Integer>> pairs = new LinkedList<>();
        if(words == null) return pairs;
        Map<String, Integer> map = new HashMap<>();
        for(int i=0; i<words.length; i++) map.put(words[i], i);
        for(int index=0; index<words.length; index++){
            String cur = words[index];
            for(int j=0; j<cur.length(); j++){
                String sub = cur.substring(0, j+1);
                StringBuilder reverse = new StringBuilder(sub).reverse();
                if(map.containsKey(reverse.toString()) && map.get(reverse.toString())!=index && isPalindrome(cur.substring(j+1)))
                    pairs.add(Arrays.asList(new Integer[]{index, map.get(reverse.toString())}));
            }
            int j = cur.length() - 1;
            for(int i=1; i<cur.length(); i++){
                String sub = cur.substring(i, j+1);
                StringBuilder reverse = new StringBuilder(sub).reverse();
                if(map.containsKey(reverse.toString()) && map.get(reverse.toString())!=index && isPalindrome(cur.substring(0, i)))
                    pairs.add(Arrays.asList(new Integer[]{map.get(reverse.toString()), index}));
            }
        }
        return pairs;
    }
    
    
    private boolean isPalindrome(String s) {
        for (int i = 0; i < s.length()/2; ++ i)
            if (s.charAt(i) != s.charAt(s.length()-1-i))
                return false;
        return true;
    }
}

Referenced from
Author:Jeanz
Link:https://www.jianshu.com/p/f08f2afe9681

Best Solution: (140ms)
public class Solution {
    public List<List<Integer>> palindromePairs(String[] words) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if(words == null || words.length == 0) return res;
        HashMap<String, Integer> map = new HashMap<>();
        for(int i = 0; i < words.length; i++) map.put(words[i], i);
        for(int i = 0; i < words.length; i++){
            for(int j = 0; j <= words[i].length(); j++){
                String str1 = words[i].substring(0, j);
                String str2 = words[i].substring(j);
                
                if(isPalindrome(str1)){
                    String str2rvs = new StringBuilder(str2).reverse().toString();
                    if(map.containsKey(str2rvs) && map.get(str2rvs) != i){
                        List<Integer> list = new ArrayList<Integer>();
                        list.add(map.get(str2rvs));
                        list.add(i);
                        res.add(list);
                    }
                } 
                if(isPalindrome(str2) && str2.length() != 0){
                    String str1rvs = new StringBuilder(str1).reverse().toString();
                    if(map.containsKey(str1rvs) && map.get(str1rvs) != i){
                        List<Integer> list = new ArrayList<Integer>();
                        list.add(i);
                        list.add(map.get(str1rvs));
                        res.add(list);
                    }
                }
            }
        }
        return res;
    }
    
    public boolean isPalindrome(String s){
        int left = 0, right = s.length() - 1;
        while(left < right){
            if(s.charAt(left++) != s.charAt(right--)) return false;
        }
        return true;
    }
}

Referenced from
Author: 大米中的大米
Link: https://segmentfault.com/a/1190000008917798

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容