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"]
回文对。题意是给一组不重复的单词,找出所有可以组成回文的单词对。
这里我给出比较通俗的解法。创建一个isPalindrome的函数帮助判断是否是回文,同时创建一个hashmap记录每个单词和他们各自的index。遍历input中的每个单词,并且按字符一位一位地将单词断开,看单词的左半边是否是回文。若是,则在hashmap中找是否有这个回文半边的另一半,若有则加入结果集。
跑一个例子说明吧。比如第一个例子中的"sssll",判断的时候,会发现ss是回文(当然,之前的s也是回文),所以需要去找sll的reverse -> lls是否存在于hashmap,发现存在,则把两者的index [2, 4]加入结果集。
时间O(n * k^2) - n个单词,K是单词的长度
空间O(n) - hashmap
Java实现
1 class Solution { 2 public List<List<Integer>> palindromePairs(String[] words) { 3 List<List<Integer>> res = new ArrayList<>(); 4 // corner case 5 if (words == null || words.length < 2) { 6 return res; 7 } 8 9 // normal case 10 HashMap<String, Integer> map = new HashMap<>(); 11 for (int i = 0; i < words.length; i++) { 12 map.put(words[i], i); 13 } 14 15 for (int i = 0; i < words.length; i++) { 16 for (int j = 0; j <= words[i].length(); j++) { 17 String str1 = words[i].substring(0, j); 18 String str2 = words[i].substring(j); 19 if (isPalindrome(str1)) { 20 String str2rvs = new StringBuilder(str2).reverse().toString(); 21 if (map.containsKey(str2rvs) && map.get(str2rvs) != i) { 22 res.add(Arrays.asList(map.get(str2rvs), i)); 23 } 24 } 25 if (str2.length() != 0 && isPalindrome(str2)) { 26 String str1rvs = new StringBuilder(str1).reverse().toString(); 27 if (map.containsKey(str1rvs) && map.get(str1rvs) != i) { 28 res.add(Arrays.asList(i, map.get(str1rvs))); 29 } 30 } 31 } 32 } 33 return res; 34 } 35 36 private boolean isPalindrome(String s) { 37 int left = 0; 38 int right = s.length() - 1; 39 while (left <= right) { 40 if (s.charAt(left) != s.charAt(right)) { 41 return false; 42 } 43 left++; 44 right--; 45 } 46 return true; 47 } 48 }
JavaScript实现
1 /** 2 * @param {string[]} words 3 * @return {number[][]} 4 */ 5 var palindromePairs = function (words) { 6 const map = words.reduce((acc, cur, i) => { 7 acc[cur] = i; 8 return acc; 9 }, {}); 10 const output = []; 11 for (const word of words) { 12 for (let j = 0; j <= word.length; j++) { 13 if (j < word.length && isPalindrome(word, j, word.length)) { 14 const rLeft = reverseSubstring(word, 0, j); 15 if (rLeft in map) { 16 output.push([map[word], map[rLeft]]); 17 } 18 } 19 if (isPalindrome(word, 0, word.length - j)) { 20 const rRight = reverseSubstring( 21 word, 22 word.length - j, 23 word.length 24 ); 25 if (rRight in map && rRight !== word) { 26 output.push([map[rRight], map[word]]); 27 } 28 } 29 } 30 } 31 return output; 32 }; 33 34 function reverseSubstring(word, start, end) { 35 let output = ''; 36 for (let i = end - 1; i >= start; i--) { 37 output += word[i]; 38 } 39 return output; 40 } 41 42 function isPalindrome(word, start, end) { 43 let left = start; 44 let right = end - 1; 45 while (left < right) { 46 if (word[left] !== word[right]) { 47 return false; 48 } 49 left += 1; 50 right -= 1; 51 } 52 return true; 53 }