(Java)-LeetCode-336. Palindrome Pairs

来源:互联网 发布:美国m2历年数据 编辑:程序博客网 时间:2024/05/20 18:46

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"]


这道题,我首先想到的是暴力破解法,每两个字符串加起来,判断是否是回文串,果然超时了。代码如下:

public class Solution {    public List<List<Integer>> palindromePairs(String[] words) {        List<List<Integer>> result = new ArrayList<List<Integer>>();for(int i = 0; i < words.length; i++){for(int j = 0; j < words.length; j++){if(i != j && (words[i].length() == 0 || words[j].length() == 0 || words[i].charAt(0) == words[j].charAt(words[j].length()-1))){if(isPalindrome(words[i]+words[j])){List<Integer> list = new ArrayList<Integer>();list.add(i);list.add(j);result.add(list);}}}}return result;    }private boolean isPalindrome(String s){int left = 0;int right = s.length()-1;while(left <= right){if(s.charAt(left) == s.charAt(right)){left++;right--;}elsereturn false;}return true;}}

然后我看tags里有trie树,然后自己异想天开,是想建立两个trie树,第一个存放正常的字符串数组,第二个存放每个字符串都反转的字符串数组,然后对数组里的每个字符串,当其作为组成回文数的第一个数时,从前往后扫描每个字符,在逆序的trie树里查找,若找到字符串,则看看剩下的子字符串是否是回文的,若是,则成功,若不是则失败。

当其作为组成回文数的第二个数时,从后往前扫描每个字符,在正序的trie树里查找,若找到字符串,则看看剩下的子字符串是否是回文的,若是,则成功,若不是则失败。

这种算法只能找到比当前字符更短的匹配字符串,不过不会遗漏。然而这种异想天开的算法也超时了,为了纪念,代码如下所示:


public class Solution {    public List<List<Integer>> palindromePairs(String[] words) {    TrieST<Integer> trieordered = new TrieST<Integer>(Alphabet.BASE64);    TrieST<Integer> trieunorder = new TrieST<Integer>(Alphabet.BASE64);    Set<List<Integer>> set = new HashSet<List<Integer>>();    int i = 0;    for(String ss: words){    trieordered.put(ss, i);    trieunorder.put(new StringBuilder(ss).reverse().toString(), i++);    }    i=0;    for(String ss:words){    List<Integer> list1 = trieordered.conPalindrome(new StringBuilder(ss).reverse().toString());    for(int num : list1){       if(num != i){        List<Integer> templist = new ArrayList<Integer>();    templist.add(num);    templist.add(i);    set.add(templist);    }    }       List<Integer> list2 = trieunorder.conPalindrome(ss);    for(int num : list2){    if(num != i){        List<Integer> templist = new ArrayList<Integer>();    templist.add(i);    templist.add(num);    set.add(templist);    }    }    i++;    }    List<List<Integer>> result = new ArrayList<List<Integer>>(set);    return result;    }}class TrieST<Value> {private Alphabet alpha;private static int R;private Node root;public TrieST(Alphabet alpha){this.alpha = alpha;R = alpha.R();}private static class Node{private Object val;private Node[] next = new Node[R];}@SuppressWarnings("unchecked")public Value get(String key){Node x = get(root, key, 0);if(x == null)return null;return (Value)x.val;}private Node get(Node x, String key, int d) {// TODO Auto-generated method stubif(x == null)return null;if(d == key.length())return x;char c = key.charAt(d);return get(x.next[alpha.toIndex(c)],key,d+1);}public void put(String key, Value v){root = put(root, key, v, 0);}private Node put(Node x, String key, Value val, int d){if(x == null)x = new Node();if(d == key.length()){x.val = val;return x;}char c = key.charAt(d);x.next[alpha.toIndex(c)] = put(x.next[alpha.toIndex(c)], key, val, d+1);return x;}public List<Value> conPalindrome(String str){List<Value> result = new ArrayList<Value>();Node node = root;int n = 0;if(node.val != null){if(isPalindrome(str.substring(n,str.length()))){result.add((Value)root.val);}}for(int i = 0 ; i < str.length(); i++){n++;char c = str.charAt(i);node = node.next[alpha.toIndex(c)];if(node == null){break;}if(node.val != null){if(isPalindrome(str.substring(n,str.length()))){result.add((Value)node.val);}}}return result;}private boolean isPalindrome(String s){int left = 0;int right = s.length()-1;while(left <= right){if(s.charAt(left) == s.charAt(right)){left++;right--;}elsereturn false;}return true;}}class Alphabet {   public static final Alphabet BASE64 = new Alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");   private char[] alphabet;     // the characters in the alphabet   private int[] inverse;       // indices   private int R;               // the radix of the alphabet   public Alphabet(String alpha) {       // check that alphabet contains no duplicate chars       boolean[] unicode = new boolean[Character.MAX_VALUE];       for (int i = 0; i < alpha.length(); i++) {           char c = alpha.charAt(i);           if (unicode[c])               throw new IllegalArgumentException("Illegal alphabet: repeated character = '" + c + "'");           unicode[c] = true;       }       alphabet = alpha.toCharArray();       R = alpha.length();       inverse = new int[Character.MAX_VALUE];       for (int i = 0; i < inverse.length; i++)           inverse[i] = -1;       // can't use char since R can be as big as 65,536       for (int c = 0; c < R; c++)           inverse[alphabet[c]] = c;   }   public int R() {       return R;   }   public int toIndex(char c) {       if (c >= inverse.length || inverse[c] == -1) {           throw new IllegalArgumentException("Character " + c + " not in alphabet");       }       return inverse[c];   }   public char toChar(int index) {       if (index < 0 || index >= R) {           throw new IndexOutOfBoundsException("Alphabet index out of bounds");       }       return alphabet[index];   }}


然后在网上看看其他人的想法,如下所示:

利用字典wmap保存单词 -> 下标的键值对遍历单词列表words,记当前单词为word,下标为idx:1). 若当前单词word本身为回文,且words中存在空串,则将空串下标bidx与idx加入答案2). 若当前单词的逆序串在words中,则将逆序串下标ridx与idx加入答案3). 将当前单词word拆分为左右两半left,right。     3.1) 若left为回文,并且right的逆序串在words中,则将right的逆序串下标rridx与idx加入答案          3.2) 若right为回文,并且left的逆序串在words中,则将left的逆序串下标idx与rlidx加入答案
O(k * n ^2)解法其中k为单词个数,n为单词的长度

其实1和2只是3的特殊情况

我最开始实现还是用trie树,不过这次内存不够用了(在字符串很长的情况下),本来trie树就是用空间换时间的嘛,于是换用了HashMap,就够了~代码如下:


public class Solution {    public List<List<Integer>> palindromePairs(String[] words) {    Map<String,Integer> trieordered = new HashMap<String,Integer>();    Set<List<Integer>> set = new HashSet<List<Integer>>();    int i = 0;    for(String ss: words){    trieordered.put(ss, i++);    }    i = 0;    for(String ss:words){    int len = ss.length();    for(int index = 0 ; index <= len; index++ ){    String left = ss.substring(0, index);    String right = ss.substring(index,len);    if(isPalindrome(left)){    Integer temp = trieordered.get(new StringBuilder(right).reverse().toString());    if(temp != null && temp != i){    List<Integer> list = new ArrayList<Integer>();list.add(temp);list.add(i);set.add(list);    }    }    if(isPalindrome(right)){    Integer temp = trieordered.get(new StringBuilder(left).reverse().toString());    if(temp != null && temp != i){    List<Integer> list = new ArrayList<Integer>();list.add(i);list.add(temp);set.add(list);    }    }    }    i++;    }        List<List<Integer>> result = new ArrayList<List<Integer>>(set);    return result;    }        private boolean isPalindrome(String s){int left = 0;int right = s.length()-1;while(left <= right){if(s.charAt(left) == s.charAt(right)){left++;right--;}elsereturn false;}return true;}}






0 0
原创粉丝点击