Vérifiez la chaîne pour le palindrome


93

Un palindrome est un mot, une phrase, un nombre ou une autre séquence d'unités qui peut être lu de la même manière dans les deux sens.

Pour vérifier si un mot est un palindrome, j'obtiens le tableau de caractères du mot et je compare les caractères. Je l'ai testé et il semble fonctionner. Cependant, je veux savoir si c'est juste ou s'il y a quelque chose à améliorer.

Voici mon code:

public class Aufg1 {
    public static void main(String[] args) {
        String wort = "reliefpfpfeiller";
        char[] warray = wort.toCharArray(); 
        System.out.println(istPalindrom(warray));       
    }

    public static boolean istPalindrom(char[] wort){
        boolean palindrom = false;
        if(wort.length%2 == 0){
            for(int i = 0; i < wort.length/2-1; i++){
                if(wort[i] != wort[wort.length-i-1]){
                    return false;
                }else{
                    palindrom = true;
                }
            }
        }else{
            for(int i = 0; i < (wort.length-1)/2-1; i++){
                if(wort[i] != wort[wort.length-i-1]){
                    return false;
                }else{
                    palindrom = true;
                }
            }
        }
        return palindrom;
    }
}

4
Je ne sais pas si c'est intentionnel, mais la chaîne de votre exemple - reliefpfpfeiller - n'est pas un palindrome
barrowc

Réponses:


185

Pourquoi pas simplement:

public static boolean istPalindrom(char[] word){
    int i1 = 0;
    int i2 = word.length - 1;
    while (i2 > i1) {
        if (word[i1] != word[i2]) {
            return false;
        }
        ++i1;
        --i2;
    }
    return true;
}

Exemple:

L'entrée est "andna".
i1 sera 0 et i2 sera 4.

Première itération de boucle, nous comparerons word[0]et word[4]. Ils sont égaux, donc nous incrémentons i1 (c'est maintenant 1) et décrémentons i2 (c'est maintenant 3).
Nous comparons donc les n. Ils sont égaux, donc nous incrémentons i1 (c'est maintenant 2) et décrémentons i2 (c'est 2).
Maintenant, i1 et i2 sont égaux (ils sont tous les deux 2), donc la condition de la boucle while n'est plus vraie, donc la boucle se termine et nous retournons true.


1
au lieu de pré-incrément (++ i1 et --i2), nous pouvons également utiliser le résultat de post-incrément (i1 ++, i2 -) est le même je pense!
user0946076422

@ user0946076422 Oui. Moi aussi, je ressentais cela. Ce serait formidable si OP avait une explication différente.
Vijay Tholpadi

3
@Vijay Tholpadi - C'est vraiment une préférence de codage plus que toute autre chose. L'incrémentation de post obtiendrait le même résultat dans cet exemple particulier, mais j'utilise toujours pré incrémentation sauf s'il y a une raison spécifique de ne pas le faire.
dcp

118

Vous pouvez vérifier si une chaîne est un palindrome en le comparant à l'inverse de lui-même:

public static boolean isPalindrome(String str) {
    return str.equals(new StringBuilder(str).reverse().toString());
}

ou pour les versions de Java antérieures à 1.5,

public static boolean isPalindrome(String str) {
    return str.equals(new StringBuffer().append(str).reverse().toString());
}

EDIT: @FernandoPelliccioni a fourni une analyse très approfondie de l'efficacité (ou de son absence) de cette solution, à la fois en termes de temps et d'espace. Si vous êtes intéressé par la complexité de calcul de cette question et d'autres solutions possibles à cette question, veuillez la lire!


10
Comparez la complexité de votre algorithme par rapport aux autres.
Fernando Pelliccioni

2
@FernandoPelliccioni, je pense que c'est la même complexité que les autres solutions, non?
aioobe

1
@Fernando, pour autant que je sache, toutes les réponses ont une complexité linéaire. Pour cette raison, il n'y a aucun moyen de donner une réponse définitive à la solution la plus efficace. Vous pouvez exécuter des tests de performance, mais ils seraient spécifiques à une JVM et un JRE particuliers. Bonne chance avec votre article de blog. En attente de le lire.
aioobe

1
@FernandoPelliccioni belle analyse
Saravana

1
@FernandoPelliccioni qui était épique
Matthew Moisen

66

Une version concise, qui n'implique pas (de manière inefficace) l'initialisation d'un groupe d'objets:

boolean isPalindrome(String str) {    
    int n = str.length();
    for( int i = 0; i < n/2; i++ )
        if (str.charAt(i) != str.charAt(n-i-1)) return false;
    return true;    
}

18

Alternativement, récursivité .

Pour quiconque cherche une solution récursive plus courte, pour vérifier si une chaîne donnée satisfait en tant que palindrome:

private boolean isPalindrome(String s) {
    int length = s.length();

    if (length < 2) // If the string only has 1 char or is empty
        return true;
    else {
        // Check opposite ends of the string for equality
        if (s.charAt(0) != s.charAt(length - 1))
            return false;
        // Function call for string with the two ends snipped off
        else
            return isPalindrome(s.substring(1, length - 1));
    }
}

OU encore plus court , si vous le souhaitez:

private boolean isPalindrome(String s) {
    int length = s.length();
    if (length < 2) return true;
    return s.charAt(0) != s.charAt(length - 1) ? false :
            isPalindrome(s.substring(1, length - 1));
}

3
Bon code, la récursivité le rend vraiment facile et moins de lignes sur le code.
Akash5288

2
la version plus courte peut être simplifiée:return s.charAt(0) == s.charAt(l - 1) && isPalindrome(s.substring(1, l - 1));
vault

10

Allez, Java:

public boolean isPalindrome (String word) {
    String myWord = word.replaceAll("\\s+","");
    String reverse = new StringBuffer(myWord).reverse().toString();
    return reverse.equalsIgnoreCase(myWord);
}

isPalindrome("Never Odd or Even"); // True
isPalindrome("Never Odd or Even1"); // False

Celles-ci me semblaient la solution la plus simple et la plus directe. Merci!
RShome le

4

également une solution d'apparence différente:

public static boolean isPalindrome(String s) {

        for (int i=0 , j=s.length()-1 ; i<j ; i++ , j-- ) {

            if ( s.charAt(i) != s.charAt(j) ) {
                return false;
            }
        }

        return true;
    }

4

Et voici une solution complète de streaming Java 8 . Un IntStream fournit tous les index jusqu'à la moitié des chaînes, puis une comparaison du début et de la fin est effectuée.

public static void main(String[] args) {
    for (String testStr : Arrays.asList("testset", "none", "andna", "haah", "habh", "haaah")) {
        System.out.println("testing " + testStr + " is palindrome=" + isPalindrome(testStr));
    }
}

public static boolean isPalindrome(String str) {
    return IntStream.range(0, str.length() / 2)
            .noneMatch(i -> str.charAt(i) != str.charAt(str.length() - i - 1));
}

La sortie est:

testing testset is palindrome=true
testing none is palindrome=false
testing andna is palindrome=true
testing haah is palindrome=true
testing habh is palindrome=false
testing haaah is palindrome=true

1
Pourquoi pas allMatchavec allMatch(i -> str.charAt(i) == str.charAt(str.length() - i - 1))?
gil.fernandes

4
public class Palindromes {
    public static void main(String[] args) {
         String word = "reliefpfpfeiller";
         char[] warray = word.toCharArray(); 
         System.out.println(isPalindrome(warray));       
    }

    public static boolean isPalindrome(char[] word){
        if(word.length%2 == 0){
            for(int i = 0; i < word.length/2-1; i++){
                if(word[i] != word[word.length-i-1]){
                    return false;
                }
            }
        }else{
            for(int i = 0; i < (word.length-1)/2-1; i++){
                if(word[i] != word[word.length-i-1]){
                    return false;
                }
            }
        }
        return true;
    }
}

2
simplifié un peu. mais j'aime la réponse de dcp!
Casey

Avez-vous essayé de courir isPalindrome()avec "cbb"?
kenshinji

3
public class palindrome {
public static void main(String[] args) {
    StringBuffer strBuf1 = new StringBuffer("malayalam");
    StringBuffer strBuf2 = new StringBuffer("malayalam");
    strBuf2.reverse();


    System.out.println(strBuf2);
    System.out.println((strBuf1.toString()).equals(strBuf2.toString()));
    if ((strBuf1.toString()).equals(strBuf2.toString()))
        System.out.println("palindrome");
    else
        System.out.println("not a palindrome");
}

}


3

J'ai travaillé sur une solution pour une question qui a été marquée comme duplicata de celle-ci. Autant le lancer ici ...

La question demandait une seule ligne pour résoudre ce problème, et je l'ai plutôt considérée comme le palindrome littéraire - donc les espaces, la ponctuation et les majuscules / minuscules peuvent gâcher le résultat.

Voici la solution laide avec une petite classe de test:

public class Palindrome {
   public static boolean isPalendrome(String arg) {
         return arg.replaceAll("[^A-Za-z]", "").equalsIgnoreCase(new StringBuilder(arg).reverse().toString().replaceAll("[^A-Za-z]", ""));
   }
   public static void main(String[] args) {
      System.out.println(isPalendrome("hiya"));
      System.out.println(isPalendrome("star buttons not tub rats"));
      System.out.println(isPalendrome("stab nail at ill Italian bats!"));
      return;
   }
}

Désolé que ce soit un peu méchant - mais l'autre question spécifiait un one-liner.


1
Juste curieux, pourquoi l'opérateur ternaire à la fin?
typingduck

Absolument rien - je n'ai pas dû prendre mon café. Fixera ma réponse - merci !.
Marc

3

En vérifiant le palindrome pour la première moitié de la corde avec le reste, ce cas suppose la suppression de tous les espaces blancs.

public int isPalindrome(String a) {
        //Remove all spaces and non alpha characters
        String ab = a.replaceAll("[^A-Za-z0-9]", "").toLowerCase();
        //System.out.println(ab);

        for (int i=0; i<ab.length()/2; i++) {
            if(ab.charAt(i) != ab.charAt((ab.length()-1)-i)) {
                return 0;
            }
        }   
        return 1;
    }

2

Je suis nouveau sur Java et je prends votre question comme un défi pour améliorer mes connaissances.

import java.util.ArrayList;
import java.util.List;

public class PalindromeRecursiveBoolean {

    public static boolean isPalindrome(String str) {

        str = str.toUpperCase();
        char[] strChars = str.toCharArray();

        List<Character> word = new ArrayList<>();
        for (char c : strChars) {
            word.add(c);
        }

        while (true) {
            if ((word.size() == 1) || (word.size() == 0)) {
                return true;
            }
            if (word.get(0) == word.get(word.size() - 1)) {
                word.remove(0);
                word.remove(word.size() - 1);
            } else {
                return false;

            }

        }
    }
}
  1. Si la chaîne est composée d'aucune lettre ou d'une seule lettre, c'est un palindrome.
  2. Sinon, comparez les première et dernière lettres de la chaîne.
    • Si la première et la dernière lettre diffèrent, la chaîne n'est pas un palindrome
    • Sinon, la première et la dernière lettre sont identiques. Retirez-les de la chaîne et déterminez si la chaîne qui reste est un palindrome. Prenez la réponse pour cette chaîne plus petite et utilisez-la comme réponse pour la chaîne d'origine, puis répétez à partir de 1 .

1

Essayez ceci:

import java.util.*;
    public class str {

        public static void main(String args[])
        {
          Scanner in=new Scanner(System.in);
          System.out.println("ENTER YOUR STRING: ");
          String a=in.nextLine();
          System.out.println("GIVEN STRING IS: "+a);
          StringBuffer str=new StringBuffer(a);
          StringBuffer str2=new StringBuffer(str.reverse());
          String s2=new String(str2);
          System.out.println("THE REVERSED STRING IS: "+str2);
            if(a.equals(s2))    
                System.out.println("ITS A PALINDROME");
            else
                System.out.println("ITS NOT A PALINDROME");
            }
    }

1
public boolean isPalindrome(String abc){
    if(abc != null && abc.length() > 0){
        char[] arr = abc.toCharArray();
        for (int i = 0; i < arr.length/2; i++) {
            if(arr[i] != arr[arr.length - 1 - i]){
                return false;
            }
        }
        return true;
    }
    return false;
}

1

Une autre façon consiste à utiliser char Array

public class Palindrome {

public static void main(String[] args) {
    String str = "madam";
    if(isPalindrome(str)) {
        System.out.println("Palindrome");
    } else {
        System.out.println("Not a Palindrome");
    }
}

private static boolean isPalindrome(String str) {
    // Convert String to char array
    char[] charArray = str.toCharArray();  
    for(int i=0; i < str.length(); i++) {
        if(charArray[i] != charArray[(str.length()-1) - i]) {
            return false;
        }
    }
    return true;
}

}


1
Cette approche est excellente. Complexité temporelle O (n), Complexité spatiale O (1)
kanaparthikiran

1

Voici mon analyse de la réponse @Greg: componentsprogramming.com/palindromes


Sidenote: Mais, pour moi, il est important de le faire de manière générique . Les exigences sont que la séquence soit itérable bidirectionnellement et que les éléments de la séquence soient comparables en utilisant l'égalité. Je ne sais pas comment le faire en Java, mais, voici une version C ++, je ne connais pas de meilleure façon de le faire pour les séquences bidirectionnelles.

template <BidirectionalIterator I> 
    requires( EqualityComparable< ValueType<I> > ) 
bool palindrome( I first, I last ) 
{ 
    I m = middle(first, last); 
    auto rfirst = boost::make_reverse_iterator(last); 
    return std::equal(first, m, rfirst); 
} 

Complexité: temps linéaire,

  • Si I est RandomAccessIterator: comparaisons floor (n / 2) et floor (n / 2) * 2 itérations

  • Si I est BidirectionalIterator: floor (n / 2) comparissons et floor (n / 2) * 2 itérations plus (3/2) * n itérations pour trouver le milieu (fonction du milieu)

  • stockage: O (1)

  • Pas de mémoire allouée dynamique



1

Récemment, j'ai écrit un programme palindrome qui n'utilise pas StringBuilder. Une réponse tardive mais cela pourrait être utile à certaines personnes.

public boolean isPalindrome(String value) {
    boolean isPalindrome = true;
    for (int i = 0 , j = value.length() - 1 ; i < j ; i ++ , j --) {
        if (value.charAt(i) != value.charAt(j)) {
            isPalindrome = false;
        }
    }
    return isPalindrome;
}

1

En utilisant stack, cela peut être fait comme ça

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
import java.util.*;

public class Solution {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str=in.nextLine();
        str.replaceAll("\\s+","");
        //System.out.println(str);
        Stack<String> stack=new Stack<String>();
        stack.push(str);
        String str_rev=stack.pop();
        if(str.equals(str_rev)){
            System.out.println("Palindrome"); 
        }else{
             System.out.println("Not Palindrome");
        }
    }
}

comme vous devez le savoir, la pile est de type LIFO, ce qui signifie que vous êtes essentiellement en train de pousser des données au début de la pile et de récupérer des données à la fin de la pile en utilisant pop (). J'espère que cela t'aides!
aayushi

1
 public static boolean isPalindrome(String word) {
    String str = "";
    for (int i=word.length()-1; i>=0;  i--){
        str = str + word.charAt(i);
    }
   if(str.equalsIgnoreCase(word)){
       return true;
   }else{
       return false;
   }

}

1

Étonnant combien de solutions différentes à un problème aussi simple existent! En voici un autre.

private static boolean palindrome(String s){
    String revS = "";
    String checkS = s.toLowerCase();
    String[] checkSArr = checkS.split("");

    for(String e : checkSArr){
        revS = e + revS;
    }

    return (checkS.equals(revS)) ? true : false;
}

1
  • Cette implémentation fonctionne pour les nombres et les chaînes.
  • Puisque nous n'écrivons rien, il n'est donc pas nécessaire de convertir la chaîne en tableau de caractères.
public static boolean isPalindrome(Object obj)
{
    String s = String.valueOf(obj);

    for(int left=0, right=s.length()-1; left < right; left++,right--)
    {
        if(s.charAt(left++) != s.charAt(right--))
            return false;
    }
    return true;
}

1

Pourquoi pas simplement:

boolean isPalindrom(String s) {
        char[] myChars = s.toCharArray();
        for (int i = 0; i < myChars.length/2; i++) {
            if (myChars[i] != myChars[myChars.length - 1 - i]) {
                return false;
            }
        }
        return true;
}

0
import java.util.Scanner;


public class Palindrom {

    public static void main(String []args)
    {
        Scanner in = new Scanner(System.in);
        String str= in.nextLine();
        int x= str.length();

        if(x%2!=0)
        {
            for(int i=0;i<x/2;i++)
            {

                if(str.charAt(i)==str.charAt(x-1-i))
                {
                    continue;
                }
                else 
                {
                    System.out.println("String is not a palindrom");
                    break;
                }
            }
        }
        else
        {
            for(int i=0;i<=x/2;i++)
            {
                if(str.charAt(i)==str.charAt(x-1-i))
                {
                    continue;
                }
                else 
                {
                    System.out.println("String is not a palindrom");
                    break;
                }

            }
        }
    }

}

0
private static boolean isPalindrome(String word) {

        int z = word.length();
        boolean isPalindrome = false;

        for (int i = 0; i <= word.length() / 2; i++) {
            if (word.charAt(i) == word.charAt(--z)) {
                isPalindrome = true;
            }
        }

        return isPalindrome;
    }

0

Je cherchais une solution qui ne fonctionnait pas seulement pour les palindromes comme ...

  • "Kayak"
  • "Madame"

... mais aussi pour ...

  • "Un homme, un plan, un canal, Panama!"
  • "Est-ce que c'était une voiture ou un chat que j'ai vu?"
  • "Pas de 'x' dans Nixon"

Itératif : cela s'est avéré être une bonne solution.

private boolean isPalindromeIterative(final String string)
    {
        final char[] characters =
            string.replaceAll("[\\W]", "").toLowerCase().toCharArray();

        int iteratorLeft = 0;
        int iteratorEnd = characters.length - 1;

        while (iteratorEnd > iteratorLeft)
        {
            if (characters[iteratorLeft++] != characters[iteratorEnd--])
            {
                return false;
            }
        }

        return true;
    }

Récursif . Je pense que cette solution ne devrait pas être bien pire que la solution itérative. Est-ce un peu merdique que nous devons extraire l'étape de nettoyage de la méthode pour éviter un traitement inutile.

private boolean isPalindromeRecursive(final String string)
        {
            final String cleanString = string.replaceAll("[\\W]", "").toLowerCase();
            return isPalindromeRecursiveRecursion(cleanString);
        }

private boolean isPalindromeRecursiveRecursion(final String cleanString)
        {
            final int cleanStringLength = cleanString.length();

            return cleanStringLength <= 1 || cleanString.charAt(0) ==
                       cleanString.charAt(cleanStringLength - 1) &&
                       isPalindromeRecursiveRecursion  
                           (cleanString.substring(1, cleanStringLength - 1));
        }

Inverser : cela s'est avéré être une solution coûteuse.

private boolean isPalindromeReversing(final String string)
    {
        final String cleanString = string.replaceAll("[\\W]", "").toLowerCase();
        return cleanString.equals(new StringBuilder(cleanString).reverse().toString());
    }

Tous les crédits aux gars qui ont répondu dans cet article et ont mis en lumière le sujet.


0

Ne considérant pas les lettres dans les mots

public static boolean palindromeWords(String s ){

        int left=0;
        int right=s.length()-1;

        while(left<=right){

            while(left<right && !Character.isLetter(s.charAt(left))){
                left++;
            }
            while(right>0 && !Character.isLetter(s.charAt(right))){
                right--;
            }

            if((s.charAt(left++))!=(s.charAt(right--))){
                return false;
            }
        }
        return true;
    }

———

@Test
public void testPalindromeWords(){
    assertTrue(StringExercise.palindromeWords("ece"));
    assertTrue(StringExercise.palindromeWords("kavak"));
    assertFalse(StringExercise.palindromeWords("kavakdf"));
    assertTrue(StringExercise.palindromeWords("akka"));
    assertTrue(StringExercise.palindromeWords("??e@@c_--e"));
}

0

Ici, vous pouvez vérifier dynamiquement un certain nombre de chaînes de palindrome

import java.util.Scanner;

public class Checkpalindrome {
 public static void main(String args[]) {
  String original, reverse = "";
  Scanner in = new Scanner(System.in);
  System.out.println("Enter How Many number of Input you want : ");
  int numOfInt = in.nextInt();
  original = in.nextLine();
do {
  if (numOfInt == 0) {
    System.out.println("Your Input Conplete");
   } 
  else {
    System.out.println("Enter a string to check palindrome");
    original = in.nextLine();

    StringBuffer buffer = new StringBuffer(original);
    reverse = buffer.reverse().toString();

  if (original.equalsIgnoreCase(reverse)) {
    System.out.println("The entered string is Palindrome:"+reverse);
   } 
  else {
    System.out.println("The entered string is not Palindrome:"+reverse);
    }
 }
   numOfInt--;
    } while (numOfInt >= 0);
}
}

0

OMI, la méthode récursive est la plus simple et la plus claire.

public static boolean isPal(String s)
{   
    if(s.length() == 0 || s.length() == 1)
        return true; 
    if(s.charAt(0) == s.charAt(s.length()-1))
       return isPal(s.substring(1, s.length()-1));                
   return false;
}

2
Cela a déjà été utilisé dans une réponse: Chaîne de vérification pour palindrome (juste une note)
Tom

désolé, je l'ai manqué.
john Smith

0

ici, en recherchant le plus grand palindrome d'une chaîne, toujours à partir du 1er caractère.

public static String largestPalindromeInString(String in) {
    int right = in.length() - 1;
    int left = 0;
    char[] word = in.toCharArray();
    while (right > left && word[right] != word[left]) {
        right--;
    }
    int lenght = right + 1;
    while (right > left && word[right] == word[left]) {

        left++;
        right--;

    }
    if (0 >= right - left) {
        return new String(Arrays.copyOf(word, lenght ));
    } else {
        return largestPalindromeInString(
                new String(Arrays.copyOf(word, in.length() - 1)));
    }
}

0

Extrait de code:

import java.util.Scanner;

 class main
 {
    public static void main(String []args)
    {
       Scanner sc = new Scanner(System.in);
       String str = sc.next();
       String reverse = new StringBuffer(str).reverse().toString();

        if(str.equals(reverse))
            System.out.println("Pallindrome");
        else
            System.out.println("Not Pallindrome");
     }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.