Airbnb: Palindromic pair of a list of strings


LeetCode 336 - Palindrome Pairs
Buttercola: Airbnb: Palindromic pair of a list of strings
Given a list of strings, find all the palindromic pairs of the string and output the concatenated palindrome.

e.g. [abc, cba], output is abccba, cbaabc.
e.g. [aabc, cb], output is cbaabc



Understand the problem:

The brute-force solution to this problem is very simple. For each word, we search all the others and see if it can form a palindrome. Assume that the ave. length of each word is m and there are totally n words in the list, the time complexity would be O(n^2 * m). 

Solution:
A better solution is for a given word, we put all its possible words which can form a palindrome into a HashMap. Then for another word, if it is in the map, we know that it is a pair which can forma a palindrome. Note that a word can form a palindrome from front and end, e.g. [abc, cba], the palindrome could be either abccba and cbaabc. So we need to maintain two maps and store the candidate words which can be in the front and end. 
The key of the map is the candidate words, and the value is the list of the original words. 
  public List<String> getPalindromicPairs(String[] input) {
    List<String> result = new ArrayList<>();
    if (input == null || input.length < 2) {
      return result;
    }
     
    // Step 1: add all the revsered order of all
    // words into the set
    Map<String, Integer> map = new HashMap<>();
    for (String str : input) {
      String reverseStr = reverse(str);
      if (!map.containsKey(reverseStr)) {
        map.put(reverseStr, 1);
      } else {
        map.put(reverseStr, map.get(reverseStr) + 1);
      }
    }
     
    for (String str : input) {
      // Iterate all prefix
      for (int i = 1; i <= str.length(); i++) {
        String prefix = str.substring(0, i);
        String postfix = str.substring(i);
         
        if (map.containsKey(prefix) && isPalindrome(postfix)) {
          String reversedStr = reverse(prefix);
          if (!prefix.equals(reversedStr) || (prefix.equals(reversedStr) && map.get(prefix) % 2 == 0)) {
            String tmp = str + reverse(prefix);
            result.add(tmp);
          }
        }
      }
       
      // Iterate all postfix
      for (int i = str.length() - 1; i >= 0; i--) {
        String postfix = str.substring(i);
        String prefix = str.substring(0, i);
         
        if (map.containsKey(postfix) && isPalindrome(prefix)) {
          String rePostfix = reverse(postfix);
          if (!postfix.equals(rePostfix) || (postfix.equals(rePostfix) && map.get(postfix) % 2 == 0)) {
           String tmp = reverse(postfix) + str;
           result.add(tmp);
          }
        }
      }
    }
     
    return result;
     
  }
   
  private String reverse(String s) {
    if (s == null || s.length() == 0) {
      return s;
    }
     
    char[] arr = s.toCharArray();
    int lo = 0;
    int hi = arr.length - 1;
     
    while (lo < hi) {
      char temp = arr[lo];
      arr[lo] = arr[hi];
      arr[hi] = temp;
       
      lo++;
      hi--;
    }
     
    return new String(arr);
  }
   
  private boolean isPalindrome(String s) {
    if (s == null || s.length() <= 1) {
      return true;
    }
     
    int lo = 0;
    int hi = s.length() - 1;
     
    while (lo < hi) {
      if (s.charAt(lo) != s.charAt(hi)) {
        return false;
      }
       
      lo++;
      hi--;
    }
     
    return true;
  }

Palindrome Pairs – AlgoBox by dietpepsi
Given a list of unique words. Find all pairs of 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"]
Posts: GoogleGoogleAirbnb
Put all words in a Set. For each word, get all it’s prefix and suffix. Search for reversed(prefix) and reversed(suffix) in the Set.
If found, check if the rest of the string is a palindrome or not. Time complexity O(nk^2).
    public List<List<Integer>> parlindromePairs(String[] words) {
        List<List<Integer>> ans = new ArrayList<>();
        Map<String, Integer> map = new HashMap<>();
        for (int i = 0; i < words.length; ++i) map.put(words[i], i);
        for (int k = 0; k < words.length; ++k) {
            String word = words[k];
            int n = word.length();
            for (int i = 0; i < n + 1; ++i) {
                String suffix = new StringBuilder(word.substring(0, i)).reverse().toString();
                String prefix = new StringBuilder(word.substring(i, n)).reverse().toString();
                if (i != 0 && map.containsKey(prefix) && map.get(prefix) != k && isPalindrome(suffix))
                    ans.add(Arrays.asList(map.get(prefix), k));
                if (map.containsKey(suffix) && map.get(suffix) != k && isPalindrome(prefix))
                    ans.add(Arrays.asList(k, map.get(suffix)));
            }
        }
        return ans;
    }
    public boolean isPalindrome(String word) {
        for (int i = 0; i < word.length() / 2; ++i)
            if (word.charAt(i) != word.charAt(word.length() - i - 1)) return false;
        return true;
    }

Method 2

  1. Preprocess all words using Manacher’s Algorithm and save the results. The step is O(nk).
  2. Build a Trie of all words. O(nk).
  3. For each word search reversed word in the trie, if found partial match, use the preprocess results to check if the rest of the string is a palindrome in O(1). The step is O(nk).
  4. Build a Trie of all reversed words. O(nk).
  5. For each word search it in the reversed Trie, if found partial match, use the preprocess results to check if the rest of the string is a palindrome in O(1). The step is O(nk).


Total time complexity is O(nk).
Read full article from Buttercola: Airbnb: Palindromic pair of a list of strings

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts