Überprüfen Sie die Zeichenfolge auf Palindrom


93

Ein Palindrom ist ein Wort, eine Phrase, eine Zahl oder eine andere Folge von Einheiten, die in beide Richtungen gleich gelesen werden können.

Um zu überprüfen, ob ein Wort ein Palindrom ist, erhalte ich das Zeichenarray des Wortes und vergleiche die Zeichen. Ich habe es getestet und es scheint zu funktionieren. Ich möchte jedoch wissen, ob es richtig ist oder ob es etwas zu verbessern gibt.

Hier ist mein 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
Ich bin mir nicht sicher, ob dies beabsichtigt ist, aber die Zeichenfolge in Ihrem Beispiel - reliefpfpfeiller - ist kein Palindrom
barrowc

Antworten:


185

Warum nicht einfach:

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;
}

Beispiel:

Eingabe ist "andna".
i1 ist 0 und i2 ist 4.

Erste Schleifeniteration werden wir vergleichen word[0]und word[4]. Sie sind gleich, also erhöhen wir i1 (es ist jetzt 1) und verringern i2 (es ist jetzt 3).
Also vergleichen wir dann die n. Sie sind gleich, also erhöhen wir i1 (es ist jetzt 2) und verringern i2 (es ist 2).
Jetzt sind i1 und i2 gleich (beide sind 2), daher ist die Bedingung für die while-Schleife nicht mehr wahr, sodass die Schleife endet und wir true zurückgeben.


1
Anstelle von Pre-Inkrement (++ i1 und --i2) können wir auch Post-Inkrement (i1 ++, i2 -) verwenden. Das Ergebnis ist meiner Meinung nach dasselbe!
user0946076422

@ user0946076422 Ja. Auch ich fühlte mich so. Wäre toll, wenn OP eine andere Erklärung hat.
Vijay Tholpadi

3
@ Vijay Tholpadi - Es ist wirklich mehr als alles andere eine Codierungspräferenz. Post-Inkrement würde in diesem Beispiel das gleiche Ergebnis erzielen, aber ich verwende immer Pre-Inkrement, es sei denn, es gibt einen bestimmten Grund, dies nicht zu tun.
DCP

118

Sie können überprüfen, ob eine Zeichenfolge ein Palindrom ist, indem Sie sie mit der Umkehrung ihrer selbst vergleichen:

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

oder für Java-Versionen vor 1.5,

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

EDIT: @FernandoPelliccioni lieferte eine sehr gründliche Analyse der Effizienz (oder des Fehlens) dieser Lösung in Bezug auf Zeit und Raum. Wenn Sie an der rechnerischen Komplexität dieser und anderer möglicher Lösungen für diese Frage interessiert sind, lesen Sie sie bitte!


10
Vergleichen Sie die Komplexität Ihres Algorithmus mit anderen.
Fernando Pelliccioni

2
@FernandoPelliccioni, ich denke, es ist die gleiche Komplexität wie die anderen Lösungen, nicht wahr?
Aioobe

1
@ Fernando, soweit ich das beurteilen kann, haben alle Antworten eine lineare Komplexität. Aus diesem Grund gibt es keine Möglichkeit, eine endgültige Antwort darauf zu geben, welche Lösung am effizientesten ist. Sie könnten Benchmarks ausführen, diese sind jedoch für eine bestimmte JVM und JRE spezifisch. Viel Glück mit Ihrem Blog-Beitrag. Ich freue mich darauf, es zu lesen.
Aioobe

1
@ FernandoPelliccioni schöne Analyse
Saravana

1
@ FernandoPelliccioni das war episch
Matthew Moisen

66

Eine prägnante Version, bei der eine Reihe von Objekten nicht (ineffizient) initialisiert wird:

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

Alternativ Rekursion .

Für alle, die nach einer kürzeren rekursiven Lösung suchen, um zu überprüfen, ob eine bestimmte Zeichenfolge als Palindrom erfüllt:

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));
    }
}

ODER noch kürzer , wenn Sie möchten:

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
Schöner Code, Rekursion macht es wirklich einfach und weniger Zeilen im Code.
Akash5288

2
Die kürzere Version kann vereinfacht werden:return s.charAt(0) == s.charAt(l - 1) && isPalindrome(s.substring(1, l - 1));
Tresor

10

Los, 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

Dies schien mir die einfachste und direkteste Lösung zu sein. Vielen Dank!
RShome

4

auch eine anders aussehende Lösung:

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

Und hier eine komplette Java 8- Streaming- Lösung. Ein IntStream liefert alle Indizes bis zu Strings halber Länge, und dann wird ein Vergleich von Anfang bis Ende durchgeführt.

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));
}

Ausgabe ist:

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
Warum nicht allMatchmit 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
etwas vereinfacht. aber ich mag die Antwort von dcp!
Casey

Haben Sie versucht , läuft isPalindrome()mit "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

Ich arbeitete an einer Lösung für eine Frage, die als Duplikat dieser Frage markiert war. Könnte es auch hier werfen ...

Die Frage verlangte eine einzige Zeile, um dies zu lösen, und ich nahm sie eher als literarisches Palindrom - also können Leerzeichen, Interpunktion und Groß- / Kleinschreibung das Ergebnis beeinträchtigen.

Hier ist die hässliche Lösung mit einer kleinen Testklasse:

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;
   }
}

Tut mir leid, dass es irgendwie böse ist - aber die andere Frage spezifizierte einen Einzeiler.


1
Nur neugierig, warum der ternäre Operator am Ende?
Typingduck

Absolut nichts - ich darf meinen Kaffee nicht getrunken haben. Wird meine Antwort korrigieren - danke!.
Marc

3

Wenn Sie das Palindrom auf die erste Hälfte der Saite mit dem Rest prüfen, wird davon ausgegangen, dass alle Leerzeichen entfernt werden.

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

Ich bin neu in Java und nehme Ihre Frage als Herausforderung an, um mein Wissen zu verbessern.

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. Wenn die Zeichenfolge aus keinen Buchstaben oder nur einem Buchstaben besteht, handelt es sich um ein Palindrom.
  2. Vergleichen Sie andernfalls den ersten und den letzten Buchstaben der Zeichenfolge.
    • Wenn sich der erste und der letzte Buchstabe unterscheiden, ist die Zeichenfolge kein Palindrom
    • Ansonsten sind der erste und der letzte Buchstabe gleich. Entfernen Sie sie von der Zeichenfolge und stellen Sie fest, ob die verbleibende Zeichenfolge ein Palindrom ist. Nehmen Sie die Antwort für diese kleinere Zeichenfolge und verwenden Sie sie als Antwort für die ursprüngliche Zeichenfolge. Wiederholen Sie dann ab 1 .

1

Probieren Sie es aus:

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

Eine andere Möglichkeit ist die Verwendung von 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
Dieser Ansatz ist ausgezeichnet. Zeitkomplexität O (n),
Raumkomplexität

1

Hier meine Analyse der @ Greg-Antwort: componentsprogramming.com/palindromes


Nebenbemerkung: Aber für mich ist es wichtig, dies generisch zu tun . Die Anforderungen sind, dass die Sequenz bidirektional iterierbar ist und die Elemente der Sequenz unter Verwendung von Gleichheit vergleichbar sind. Ich weiß nicht, wie man es in Java macht, aber hier ist eine C ++ - Version, ich kenne keinen besseren Weg, um es für bidirektionale Sequenzen zu machen.

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); 
} 

Komplexität: lineare Zeit,

  • Wenn ich RandomAccessIterator bin: Floor (n / 2) Vergleiche und Floor (n / 2) * 2 Iterationen

  • Wenn ich BidirectionalIterator bin: Etagenvergleiche (n / 2) und Etagenvergleiche (n / 2) * 2 Iterationen plus (3/2) * n Iterationen, um die mittlere (mittlere Funktion) zu finden

  • Lagerung: O (1)

  • Kein Dymamus zugewiesener Speicher



1

Kürzlich habe ich ein Palindrom-Programm geschrieben, das StringBuilder nicht verwendet. Eine späte Antwort, aber dies könnte für einige Leute nützlich sein.

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

Mit Stack kann das so gemacht werden

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");
        }
    }
}

Wie Sie wissen müssen, ist der Stapel vom Typ LIFO, was bedeutet, dass Sie Daten im Grunde genommen durch den Anfang des Stapels schieben und mit pop () Daten vom Ende des Stapels abrufen. Hoffe das hilft!
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

Erstaunlich, wie viele verschiedene Lösungen für ein so einfaches Problem existieren! Hier ist ein anderes.

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
  • Diese Implementierung funktioniert für Zahlen und Zeichenfolgen.
  • Da wir nichts schreiben, besteht keine Notwendigkeit, die Zeichenfolge in das Zeichenarray zu konvertieren.
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

Warum nicht einfach:

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

Ich suchte nach einer Lösung, die nicht nur für Palindrome wie ...

  • "Kajak"
  • "Gnädige Frau"

... aber auch für ...

  • "Ein Mann, ein Plan, ein Kanal, Panama!"
  • "War es ein Auto oder eine Katze, die ich gesehen habe?"
  • "Kein 'x' in Nixon"

Iterativ : Dies hat sich als gute Lösung erwiesen.

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;
    }

Rekursiv . Ich denke, diese Lösung sollte nicht viel schlimmer sein als die iterative. Ist ein bisschen beschissen, müssen wir den Reinigungsschritt aus der Methode herausziehen, um unnötiges Verarbeiten zu vermeiden.

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));
        }

Umkehren : Dies hat sich als teure Lösung erwiesen.

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

Alle Credits an die Jungs, die in diesem Beitrag antworten und Licht in das Thema bringen.


0

Betrachtet man keine Buchstaben in den Wörtern

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

Hier können Sie Palindrom eine Reihe von Zeichenfolgen dynamisch überprüfen

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

IMO, der rekursive Weg ist der einfachste und klarste.

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
Dies wurde bereits in einer Antwort verwendet: Überprüfen Sie die Zeichenfolge auf Palindrom (nur eine Notiz)
Tom

Entschuldigung, ich habe es verpasst.
John Smith

0

Hier wird nach dem größten Palindrom in einer Zeichenfolge gesucht, immer beginnend mit dem 1. Zeichen.

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

Code-Auszug:

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");
     }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.