336. Palindrome Pairs
by Botao Xiao
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"]
Thinking:
- Method 1: Brutal force TLE
class Solution { public List<List<Integer>> palindromePairs(String[] words) { int len = words.length; List<List<Integer>> res = new ArrayList<>(); for(int i = 0; i < len; i++){ for(int j = 0; j < len; j++){ if(i == j) continue; if(isPalindrome(words[i] + words[j])){ List<Integer> temp = new ArrayList<>(); temp.add(i); temp.add(j); res.add(temp); } } } return res; } private boolean isPalindrome(String s){ int left = 0, right = s.length() - 1; char[] arr = s.toCharArray(); while(left < right){ if(arr[left++] != arr[right--]) return false; } return true; } }
- Method 2: HashMap O(N * K^2)
class Solution { public List<List<Integer>> palindromePairs(String[] words) { List<List<Integer>> res = new ArrayList<>(); if(words == null || words.length < 2) return res; Map<String, Integer> map = new HashMap<>(); for(int i = 0; i < words.length; i++){ // O(N) map.put(words[i], i); } for(int i = 0; i < words.length; i++){ // O(N * k) for(int j = 0; j <= words[i].length(); j++){ String first = words[i].substring(0, j); String second = words[i].substring(j); if(isPalindrome(first)){ // O(k) //first is palindrome, check if we have reverse of second String reverse = new StringBuilder(second).reverse().toString(); if(map.containsKey(reverse) && map.get(reverse) != i){ List<Integer> temp = new ArrayList<>(); temp.add(map.get(reverse)); temp.add(i); res.add(temp); } } if(second.length() != 0 && isPalindrome(second)){ // O(k) String reverse = new StringBuilder(first).reverse().toString(); if(map.containsKey(reverse) && map.get(reverse) != i){ List<Integer> temp = new ArrayList<>(); temp.add(i); temp.add(map.get(reverse)); res.add(temp); } } } } return res; } private boolean isPalindrome(String s){ int left = 0, right = s.length() - 1; char[] arr = s.toCharArray(); while(left < right){ if(arr[left++] != arr[right--]) return false; } return true; } }
- Method 3: Tire Tree
class Solution { private static class Node{ Node[] childs; boolean isLeaf; int index; public Node(){ this.childs = new Node[26]; } } private Node root; private void insert(String s, int index){ char[] arr = s.toCharArray(); Node temp = root; for(int i = 0; i < arr.length; i++){ if(temp.childs[arr[i] - 'a'] == null){ temp.childs[arr[i] - 'a'] = new Node(); } temp = temp.childs[arr[i] - 'a']; } temp.isLeaf = true; temp.index = index; } private Node contains(String s){ char[] arr = s.toCharArray(); Node temp = root; for(int i = 0; i < arr.length; i++){ if(temp.childs[arr[i] - 'a'] == null) return null; temp = temp.childs[arr[i] - 'a']; } return temp; } public List<List<Integer>> palindromePairs(String[] words) { this.root = new Node(); for(int i = 0; i < words.length; i++){ insert(words[i], i); } List<List<Integer>> result = new ArrayList<>(); for(int i = 0; i < words.length; i++){ for(int j = 0; j <= words[i].length(); j++){ String first = words[i].substring(0, j); String second = words[i].substring(j); if(isPalindrome(first)){ String reverse = new StringBuilder(second).reverse().toString(); Node temp = contains(reverse); if(temp != null && temp.isLeaf && temp.index != i){ result.add(Arrays.asList(temp.index, i)); } } if(second.length() != 0 && isPalindrome(second)){ String reverse = new StringBuilder(first).reverse().toString(); Node temp = contains(reverse); if(temp != null && temp.isLeaf && temp.index != i){ result.add(Arrays.asList(i, temp.index)); } } } } return result; } private boolean isPalindrome(String s){ int l = 0, r = s.length() - 1; while(l < r){ if(s.charAt(l++) != s.charAt(r--)) return false; } return true; } }
Subscribe via RSS