Par de palíndromos en una array de palabras (o strings)

Dada una lista de palabras, encuentra si alguna de las dos palabras se puede unir para formar un palíndromo.

Ejemplos: 

Input  : list[] = {"geekf", "geeks", "or", 
                            "keeg", "abc", "bc"}
Output : Yes
There is a pair "geekf" and "keeg"

Input : list[] =  {"abc", "xyxcba", "geekst", "or",
                                      "keeg", "bc"}
Output : Yes
There is a pair "abc" and "xyxcba"

Preguntado en: Entrevista de Google 

Enfoque sencillo

1- Consider each pair one by one.
2- Check if any of the pairs forms a palindrome
   after concatenating them.
3- Return true, if any such pair exists.
4- Else, return false.

Implementación:

C++

// C++ program to find if there is a pair that
// can form a palindrome.
#include<bits/stdc++.h>
using namespace std;
 
// Utility function to check if a string is a
// palindrome
bool isPalindrome(string str)
{
    int len = str.length();
 
    // compare each character from starting
    // with its corresponding character from last
    for (int i = 0; i < len/2; i++ )
        if (str[i] != str[len-i-1])
            return false;
 
    return true;
}
 
// Function to check if a palindrome pair exists
bool checkPalindromePair(vector <string> vect)
{
    // Consider each pair one by one
    for (int i = 0; i< vect.size()-1; i++)
    {
        for (int j = i+1; j< vect.size() ; j++)
        {
            string check_str;
 
            // concatenate both strings
            check_str = vect[i] + vect[j];
 
            // check if the concatenated string is
            // palindrome
            if (isPalindrome(check_str))
                return true;
 
            // check for other combination of the two strings
            check_str = vect[j] + vect[i];
            if (isPalindrome(check_str))
                return true;
        }
    }
    return false;
}
 
// Driver code
int main()
{
    vector <string> vect = {"geekf", "geeks", "or",
                            "keeg", "abc", "bc"};
 
 
    checkPalindromePair(vect)? cout << "Yes" :
                               cout << "No";
    return 0;
}

Java

// Java program to find if there is a pair that
// can form a palindrome.
import java.util.Arrays;
import java.util.List;
public class Palin_pair1 {
         
    // Utility function to check if a string is a
    // palindrome
    static boolean isPalindrome(String str)
    {
        int len = str.length();
      
        // compare each character from starting
        // with its corresponding character from last
        for (int i = 0; i < len/2; i++ )
            if (str.charAt(i) != str.charAt(len-i-1))
                return false;
      
        return true;
    }
      
    // Function to check if a palindrome pair exists
    static boolean checkPalindromePair(List<String> vect)
    {
        // Consider each pair one by one
        for (int i = 0; i< vect.size()-1; i++)
        {
            for (int j = i+1; j< vect.size() ; j++)
            {
                String check_str = "";
      
                // concatenate both strings
                check_str = check_str + vect.get(i) + vect.get(j);
      
                // check if the concatenated string is
                // palindrome
                if (isPalindrome(check_str))
                    return true;
 
                check_str = vect.get(j) + vect.get(i);
      
                // check if the concatenated string is
                // palindrome
                if (isPalindrome(check_str))
                    return true;
            }
        }
        return false;
    }
      
    // Driver code
    public static void main(String args[])
    {
        List<String> vect = Arrays.asList("geekf", "geeks", "or",
                                "keeg", "abc", "bc");
      
      
        if (checkPalindromePair(vect) == true)
            System.out.println("Yes");
        else   
            System.out.println("No");
    }
}
//This code is contributed by Sumit Ghosh

Python3

# Python3 program to find if
# there is a pair that
# can form a palindrome.
 
# Utility function to check
# if a string is a palindrome
def isPalindrome(st):
 
    length = len(st)
 
    # Compare each character
    # from starting with its
    # corresponding character from last
    for i in range(length // 2):
        if (st[i] != st[length - i - 1]):
            return False
 
    return True
 
# Function to check if a
# palindrome pair exists
def checkPalindromePair(vect):
 
    # Consider each pair one by one
    for i in range(len(vect) - 1):
        for j in range(i + 1, len(vect)):
             
            # Concatenate both strings
            check_str = vect[i] + vect[j]
 
            # Check if the concatenated
            # string is palindrome
            if (isPalindrome(check_str)):
                return True
 
            # Check for other combination
            # of the two strings
            check_str = vect[j] + vect[i]
            if (isPalindrome(check_str)):
                return True
    return False
   
# Driver code
if __name__ == "__main__":
   
    vect = ["geekf", "geeks", "or",
            "keeg", "abc", "bc"]
     
    if checkPalindromePair(vect):
        print("Yes")
    else:
        print ("No")
   
# This code is contributed by Chitranayal

C#

// C# program to find if there is a pair that
// can form a palindrome.
using System;
using System.Collections.Generic;
 
class GFG
{
         
    // Utility function to check if
    // a string is a palindrome
    static Boolean isPalindrome(String str)
    {
        int len = str.Length;
     
        // compare each character from starting
        // with its corresponding character from last
        for (int i = 0; i < len / 2; i++ )
            if (str[i] != str[len - i - 1])
                return false;
     
        return true;
    }
     
    // Function to check if a palindrome pair exists
    static Boolean checkPalindromePair(List<String> vect)
    {
        // Consider each pair one by one
        for (int i = 0; i< vect.Count - 1; i++)
        {
            for (int j = i + 1; j< vect.Count ; j++)
            {
                String check_str = "";
     
                // concatenate both strings
                check_str = check_str + vect[i] + vect[j];
     
                // check if the concatenated string is
                // palindrome
                if (isPalindrome(check_str))
                    return true;
 
                check_str = vect[j] + vect[j];
     
                // check if the concatenated string is
                // palindrome
                if (isPalindrome(check_str))
                    return true;
            }
        }
        return false;
    }
     
    // Driver code
    public static void Main(String []args)
    {
        List<String> vect = new List<String>(){"geekf", "geeks", "or",
                                                  "keeg", "abc", "bc"};
     
     
        if (checkPalindromePair(vect) == true)
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
    }
}
 
// This code is contributed by Rajput-Ji

Javascript

<script>
 
// Javascript program to find if there
// is a pair that can form a palindrome.
 
// Utility function to check if a
// string is a palindrome
function isPalindrome(str)
{
    let len = str.length;
   
    // Compare each character from starting
    // with its corresponding character from last
    for(let i = 0; i < len / 2; i++ )
        if (str[i] != str[len - i - 1])
            return false;
   
    return true;
}
 
// Function to check if a palindrome pair exists
function checkPalindromePair(vect)
{
     
    // Consider each pair one by one
    for(let i = 0; i < vect.length - 1; i++)
    {
        for(let j = i + 1; j < vect.length; j++)
        {
            let check_str = "";
   
            // Concatenate both strings
            check_str = check_str + vect[i] + vect[j];
   
            // Check if the concatenated string is
            // palindrome
            if (isPalindrome(check_str))
                return true;
 
            check_str = vect[j] + vect[i];
   
            // Check if the concatenated string is
            // palindrome
            if (isPalindrome(check_str))
                return true;
        }
    }
    return false;
}
 
// Driver code
let vect = [ "geekf", "geeks", "or",
             "keeg", "abc", "bc" ]
              
if (checkPalindromePair(vect) == true)
    document.write("Yes");
else  
    document.write("No");
 
// This code is contributed by rag2127
 
</script>
Producción

Yes

Complejidad temporal: O(n 2 k) 
Aquí n es el número de palabras de la lista yk es la longitud máxima que se comprueba para un palíndromo.

Espacio Auxiliar : O(1)

Método eficiente:

Se puede hacer de manera eficiente utilizando la estructura de datos Trie. La idea es mantener un Trie del reverso de todas las palabras. 

1) Create an empty Trie.
2) Do following for every word:-
    a) Insert reverse of current word.
    b) Also store up to which index it is 
       a palindrome.
3) Traverse list of words again and do following 
   for every word.
    a) If it is available in Trie then return true
    b) If it is partially available
         Check the remaining word is palindrome or not 
         If yes then return true that means a pair
         forms a palindrome.
         Note: Position upto which the word is palindrome
               is stored because of these type of cases.

C++

// C++ program to check if there is a pair that
// of above method using Trie
#include<bits/stdc++.h>
using namespace std;
#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
 
// Alphabet size (# of symbols)
#define ALPHABET_SIZE (26)
 
// Converts key current character into index
// use only 'a' through 'z' and lower case
#define CHAR_TO_INDEX(c) ((int)c - (int)'a')
 
// Trie node
struct TrieNode
{
    struct TrieNode *children[ALPHABET_SIZE];
    vector<int> pos; // To store palindromic
                     // positions in str
    int id;
 
    // isLeaf is true if the node represents
    // end of a word
    bool isLeaf;
};
 
// Returns new Trie node (initialized to NULLs)
struct TrieNode *getNode(void)
{
    struct TrieNode *pNode = new TrieNode;
    pNode->isLeaf = false;
    for (int i = 0; i < ALPHABET_SIZE; i++)
            pNode->children[i] = NULL;
 
    return pNode;
}
 
// Utility function to check if a string is a
// palindrome
bool isPalindrome(string str, int i, int len)
{
    // compare each character from starting
    // with its corresponding character from last
    while (i < len)
    {
        if (str[i] != str[len])
            return false;
        i++, len--;
    }
 
    return true;
}
 
// If not present, inserts reverse of key into Trie. If
// the key is prefix of a Trie node, just mark leaf node
void insert(struct TrieNode* root, string key, int id)
{
    struct TrieNode *pCrawl = root;
 
    // Start traversing word from the last
    for (int level = key.length()-1; level >=0; level--)
    {
        // If it is not available in Trie, then
        // store it
        int index = CHAR_TO_INDEX(key[level]);
        if (!pCrawl->children[index])
            pCrawl->children[index] = getNode();
 
        // If current word is palindrome till this
        // level, store index of current word.
        if (isPalindrome(key, 0, level))
            (pCrawl->pos).push_back(id);
 
        pCrawl = pCrawl->children[index];
    }
    pCrawl->id = id;
    pCrawl->pos.push_back(id);
 
    // mark last node as leaf
    pCrawl->isLeaf = true;
}
 
// Returns true if key presents in Trie, else false
void search(struct TrieNode *root, string key,
            int id, vector<vector<int> > &result)
{
    struct TrieNode *pCrawl = root;
    for (int level = 0; level < key.length(); level++)
    {
        int index = CHAR_TO_INDEX(key[level]);
 
        // If it is present also check upto which index
        // it is palindrome
        if (pCrawl->id >= 0 && pCrawl->id != id &&
            isPalindrome(key, level, key.size()-1))
            result.push_back({id, pCrawl->id});
 
        // If not present then return
        if (!pCrawl->children[index])
            return;
 
        pCrawl = pCrawl->children[index];
    }
 
    for (int i: pCrawl->pos)
    {
        if (i == id)
            continue;
        result.push_back({id, i});
    }
}
 
// Function to check if a palindrome pair exists
bool checkPalindromePair(vector <string> vect)
{
    // Construct trie
    struct TrieNode *root = getNode();
    for (int i = 0; i < vect.size(); i++)
        insert(root, vect[i], i);
 
    // Search for different keys
    vector<vector<int> > result;
    for (int i=0; i<vect.size(); i++)
    {
        search(root, vect[i], i, result);
        if (result.size() > 0)
           return true;
    }
 
    return false;
}
 
// Driver code
int main()
{
    vector <string> vect = {"geekf", "geeks", "or",
                            "keeg", "abc", "bc"};
 
 
    checkPalindromePair(vect)? cout << "Yes" :
                               cout << "No";
    return 0;
}

Java

//Java program to check if there is a pair that
//of above method using Trie
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
public class Palin_pair2 {
 
    // Alphabet size (# of symbols)
    static final int ALPHABET_SIZE = 26;
 
    // Trie node
    static class TrieNode {
        TrieNode[] children = new TrieNode[ALPHABET_SIZE];
        List<Integer> pos; // To store palindromic
                            // positions in str
        int id;
 
        // isLeaf is true if the node represents
        // end of a word
        boolean isLeaf;
 
        // constructor
        public TrieNode() {
            isLeaf = false;
            pos = new ArrayList<>();
            for (int i = 0; i < ALPHABET_SIZE; i++)
                children[i] = null;
        }
    }
 
    // Utility function to check if a string is a
    // palindrome
    static boolean isPalindrome(String str, int i, int len) {
        // compare each character from starting
        // with its corresponding character from last
        while (i < len) {
            if (str.charAt(i) != str.charAt(len))
                return false;
 
            i++;
            len--;
        }
        return true;
    }
 
    // If not present, inserts reverse of key into Trie. If
    // the key is prefix of a Trie node, just mark leaf node
    static void insert(TrieNode root, String key, int id) {
        TrieNode pCrawl = root;
 
        // Start traversing word from the last
        for (int level = key.length() - 1; level >= 0; level--) {
            // If it is not available in Trie, then
            // store it
            int index = key.charAt(level) - 'a';
            if (pCrawl.children[index] == null)
                pCrawl.children[index] = new TrieNode();
 
            // If current word is palindrome till this
            // level, store index of current word.
            if (isPalindrome(key, 0, level))
                (pCrawl.pos).add(id);
 
            pCrawl = pCrawl.children[index];
        }
        pCrawl.id = id;
        pCrawl.pos.add(id);
 
        // mark last node as leaf
        pCrawl.isLeaf = true;
    }
 
    // list to store result
    static List<List<Integer>> result;
 
    // Returns true if key presents in Trie, else false
    static void search(TrieNode root, String key, int id) {
        TrieNode pCrawl = root;
        for (int level = 0; level < key.length(); level++) {
            int index = key.charAt(level) - 'a';
 
            // If it is present also check upto which index
            // it is palindrome
            if (pCrawl.id >= 0 && pCrawl.id != id
                    && isPalindrome(key, level, key.length() - 1)) {
                List<Integer> l = new ArrayList<>();
                l.add(id);
                l.add(pCrawl.id);
                result.add(l);
            }
 
            // If not present then return
            if (pCrawl.children[index] == null)
                return;
 
            pCrawl = pCrawl.children[index];
        }
 
        for (int i : pCrawl.pos) {
            if (i == id)
                continue;
            List<Integer> l = new ArrayList<>();
            l.add(id);
            l.add(i);
            result.add(l);
        }
    }
 
    // Function to check if a palindrome pair exists
    static boolean checkPalindromePair(List<String> vect) {
         
        // Construct trie
        TrieNode root = new TrieNode();
        for (int i = 0; i < vect.size(); i++)
            insert(root, vect.get(i), i);
 
        // Search for different keys
        result = new ArrayList<>();
        for (int i = 0; i < vect.size(); i++) {
            search(root, vect.get(i), i);
 
            if (result.size() > 0)
                return true;
        }
 
        return false;
    }
 
    // Driver code
    public static void main(String args[]) {
        List<String> vect = Arrays.asList("geekf", "geeks",
                            "or", "keeg", "abc", "bc");
 
        if (checkPalindromePair(vect) == true)
            System.out.println("Yes");
        else
            System.out.println("No");
    }
}
//This code is contributed by Sumit Ghosh

C#

// C# program to check if there is
// a pair that of above method using Trie
using System;
using System.Collections.Generic;
 
class GFG
{
 
    // Alphabet size (# of symbols)
    static readonly int ALPHABET_SIZE = 26;
 
    // Trie node
    class TrieNode
    {
        public TrieNode[] children = new TrieNode[ALPHABET_SIZE];
        public List<int> pos; // To store palindromic
                              // positions in str
        public int id;
 
        // isLeaf is true if the node
        // represents end of a word
        public Boolean isLeaf;
 
        // constructor
        public TrieNode()
        {
            isLeaf = false;
            pos = new List<int>();
            for (int i = 0; i < ALPHABET_SIZE; i++)
                children[i] = null;
        }
    }
 
    // Utility function to check if
    // a string is a palindrome
    static Boolean isPalindrome(String str,
                                int i, int len)
    {
        // compare each character from starting
        // with its corresponding character from last
        while (i < len)
        {
            if (str[i] != str[len])
                return false;
 
            i++;
            len--;
        }
        return true;
    }
 
    // If not present, inserts reverse of
    // key into Trie. If the key is prefix of
    // a Trie node, just mark leaf node
    static void insert(TrieNode root,
                       String key, int id)
    {
        TrieNode pCrawl = root;
 
        // Start traversing word from the last
        for (int level = key.Length - 1;
                 level >= 0; level--)
        {
            // If it is not available in Trie,
            // then store it
            int index = key[level] - 'a';
            if (pCrawl.children[index] == null)
                pCrawl.children[index] = new TrieNode();
 
            // If current word is palindrome till this
            // level, store index of current word.
            if (isPalindrome(key, 0, level))
                (pCrawl.pos).Add(id);
 
            pCrawl = pCrawl.children[index];
        }
        pCrawl.id = id;
        pCrawl.pos.Add(id);
 
        // mark last node as leaf
        pCrawl.isLeaf = true;
    }
 
    // list to store result
    static List<List<int>> result;
 
    // Returns true if key presents
    // in Trie, else false
    static void search(TrieNode root,
                       String key, int id)
    {
        TrieNode pCrawl = root;
        for (int level = 0;
                 level < key.Length; level++)
        {
            int index = key[level] - 'a';
 
            // If it is present also check
            // upto which index it is palindrome
            if (pCrawl.id >= 0 && pCrawl.id != id &&
                isPalindrome(key, level, key.Length - 1))
            {
                List<int> l = new List<int>();
                l.Add(id);
                l.Add(pCrawl.id);
                result.Add(l);
            }
 
            // If not present then return
            if (pCrawl.children[index] == null)
                return;
 
            pCrawl = pCrawl.children[index];
        }
 
        foreach (int i in pCrawl.pos)
        {
            if (i == id)
                continue;
            List<int> l = new List<int>();
            l.Add(id);
            l.Add(i);
            result.Add(l);
        }
    }
 
    // Function to check if a palindrome pair exists
    static Boolean checkPalindromePair(List<String> vect)
    {
         
        // Construct trie
        TrieNode root = new TrieNode();
        for (int i = 0; i < vect.Count; i++)
            insert(root, vect[i], i);
 
        // Search for different keys
        result = new List<List<int>>();
        for (int i = 0; i < vect.Count; i++)
        {
            search(root, vect[i], i);
 
            if (result.Count > 0)
                return true;
        }
        return false;
    }
 
    // Driver code
    public static void Main(String []args)
    {
        List<String> vect = new List<String>(){"geekf", "geeks",
                                               "or", "keeg",
                                               "abc", "bc"};
 
        if (checkPalindromePair(vect) == true)
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
    }
}
 
// This code is contributed by Rajput-Ji
Producción

Yes

Complejidad temporal: O(nk 2 ), donde n es el número de palabras de la lista yk es la longitud máxima que se comprueba para palíndromo.
Espacio Auxiliar: O(1)

Método 3:

A continuación se muestra un programa que se basa en el algoritmo discutido anteriormente, pero en lugar de intentarlo, utiliza una estructura de datos hashmap para brindar un método eficiente de almacenamiento y recuperación.

Por lo tanto, reduce mucho la complejidad.

Implementación:

Python3

def function(wordlist):
  #storing word in reverse format along with their indices.
   
    hashmap_reverse = {word[::-1]: index for index, word in enumerate(wordlist)}
    ans = []
    #enumerating over all words and for each character of them
    for index, word in enumerate(wordlist):
        for i in range(len(word)):
          #extracting left and right of them
            left, right = word[:i+1], word[i+1:]
            #checking if left exists and is palindrome and also right is present in map
            #this is to make sure the best edge case described holds.
             
            if not len(left) == 0 and left == left[::-1] and right in hashmap_reverse and hashmap_reverse[right] != index:
                ans.append([hashmap_reverse[right], index])
               
            #normal case.
            if right == right[::-1] and left in hashmap_reverse and hashmap_reverse[left] != index:
                ans.append([index, hashmap_reverse[left]])
    if len(ans)>0:
        return True
    return False
   
   
words = ["geekf", "geeks", "or","keeg", "abc", "bc"]
print(function(words))
Producción

True

Complejidad de tiempo: O(nl) donde n = longitud de la array y l = longitud de la string más larga.
Espacio Auxiliar: O(n)

Este artículo es una contribución de Sahil Chhabra (akku) . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *