回文のチェック文字列


93

パリンドロームは、単語、語句、数字またはいずれの方向にも同じように読み取ることができる装置の他のシーケンスです。

単語が回文かどうかを確認するには、単語のchar配列を取得して、charを比較します。私はそれをテストしました、そしてそれはうまくいくようです。しかし、私はそれが正しいかどうか、または改善する必要があるかどうかを知りたいです。

これが私のコードです:

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
これが意図的なものかどうかはわかりませんが、例の文字列-liepfpffeiller-は回文ではありません
barrowc

回答:


185

なぜか:

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

例:

入力は「andna」です。
i1は0、i2は4になります。

最初のループ反復では、と比較word[0]word[4]ます。それらは等しいので、i1(現在は1)をインクリメントし、i2(現在は3)をデクリメントします。
そこで、nを比較します。それらは等しいため、i1(現在は2)をインクリメントし、i2(2です)をデクリメントします。
これでi1とi2が等しくなり(両方とも2になる)、whileループの条件がtrueでなくなったため、ループが終了し、trueが返されます。


1
事前増分(++ i1および--i2)の代わりに、事後増分(i1 ++、i2--)を使用することもできます。結果は同じだと思います。
user0946076422

@ user0946076422はい。私もそう感じました。OPが別の説明をしている場合は素晴らしいでしょう。
Vijay Tholpadi 2017年

3
@Vijay Tholpadi-それは本当に何よりも実際にコーディングの好みです。この特定の例ではポストインクリメントでも同じ結果が得られますが、特別な理由がない限り、常にプリインクリメントを使用します。
dcp

118

文字列がパリンドロームであるかどうかを、それ自体の逆と比較することで確認できます。

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

または1.5より前のバージョンのJavaの場合

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

編集: @FernandoPelliccioniは時間と空間の両方の観点から、このソリューションの効率(またはその欠如)の非常に徹底的な分析を提供しまし。これの計算の複雑さと、この質問に対する他の可能な解決策に興味がある場合は、読んでください!


10
アルゴリズムの複雑さを他のアルゴリズムと比較してください。
Fernando Pelliccioni

2
@FernandoPelliccioni、他のソリューションと同じ複雑さだと思いますか?
aioobe 2015

1
@フェルナンド、私が知る限り、すべての答えは線形の複雑さを持っています。このため、どのソリューションが最も効率的であるかについて明確な答えを出す方法はありません。ベンチマークを実行することもできますが、それらは特定のJVMおよびJREに固有のものです。あなたのブログ投稿で頑張ってください。それを読んで楽しみにしています。
aioobe

1
@FernandoPelliccioni素敵な分析
Saravana

1
壮大な@FernandoPelliccioni
Matthew Moisen

66

一連のオブジェクトを(非効率的に)初期化する必要がない簡潔なバージョン:

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

または、再帰

より短い再帰的な解決策を探している人にとって、特定の文字列が回文として満足するかどうかを確認するには:

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

または、必要に応じてさらに短くします。

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
素晴らしいコードです。再帰により、コードが非常に簡単になり、行が少なくなります。
Akash5288 2017年

2
短いバージョンを簡略化することができます:return s.charAt(0) == s.charAt(l - 1) && isPalindrome(s.substring(1, l - 1));
ボールト

10

Go、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

これらは、私にとって最も簡単で簡単な解決策のように思えました。ありがとう!
RShome

4

また、別の見た目のソリューション:

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

そして、ここに完全なJava 8 ストリーミングソリューションがあります。アンIntStreamは、文字列の半分の長ゴマすべてのインデックスを提供して、最初からと最後の比較ですが行われます。

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

出力は次のとおりです。

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
なぜないallMatchallMatch(i -> str.charAt(i) == str.charAt(str.length() - i - 1))
gil.fernandes 2018

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
少し簡略化しました。しかし、私はdcpの答えが好きです!
Casey

で実行isPalindrome()してみました"cbb"か?
建真寺

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

私はこの問題の重複としてマークされた質問の解決策に取り組みました。ここに投げてもいいかも…

質問はこれを解決するために単一の行を要求しました、そして私はそれを文学的回文としてもっととらえました-それでスペース、句読点と大文字と小文字が結果を捨てる可能性があります。

これは、小さなテストクラスを使用した醜いソリューションです。

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

ちょっと厄介ですが、他の質問ではワンライナーを指定しています。


1
気になるだけなのに、なぜ最後に三項演算子を使うのですか?
typingduck

絶対に何もない-私は私のコーヒーを持っていなかったにちがいない。私の応答を修正します-ありがとう!。
Marc

3

残りの部分で文字列の前半のパリンドロームをチェックします。このケースでは、空白の削除を想定しています。

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

私はJavaを使い始めたばかりです。私の知識を向上させるための挑戦として、あなたの質問を取り上げます。

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. 文字列が文字なしまたは1文字だけで構成されている場合、それは回文です。
  2. それ以外の場合は、文字列の最初と最後の文字を比較します。
    • 最初と最後の文字が異なる場合、文字列は回文ではありません
    • それ以外の場合、最初と最後の文字は同じです。文字列からそれらを取り除き、残っている文字列が回文かどうかを判断します。この小さい文字列の答えを取り、それを元の文字列の答えとして使用して、1から繰り返します。

1

これを試してください:

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

別の方法はchar配列を使用することです

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
このアプローチは優れています。時間複雑度O(n)、空間複雑度O(1)
カナパルティキラン

1

@Greg回答の私の分析:componentsprogramming.com/palindromes


補足:しかし、私にとっては、一般的な方法でそれを行うことが重要です。要件は、シーケンスが双方向に反復可能であり、シーケンスの要素が等価性を使用して比較できることです。Javaでそれを行う方法はわかりませんが、ここにC ++バージョンがあります。双方向シーケンスでそれを行うためのより良い方法がわかりません。

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

複雑さ:線形時間、

  • IがRandomAccessIteratorの場合:floor(n / 2)の比較とfloor(n / 2)* 2の反復

  • IがBidirectionalIteratorの場合:floor(n / 2)の比較と、floor(n / 2)* 2の反復に(3/2)* nの反復を加えて、中央を見つけます(middle関数)

  • ストレージ:O(1)

  • 動的に割り当てられたメモリはありません



1

最近、StringBuilderを使用しない回文プログラムを作成しました。遅い回答ですが、これは一部の人にとって便利な場合があります。

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

スタックを使用すると、このようにすることができます

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

ご存じのとおり、スタックはLIFOタイプです。つまり、基本的にはスタックの最初からデータをプッシュし、pop()を使用してスタックの最後からデータを取得します。お役に立てれば!
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

このような単純な問題に対する解決策がいくつ存在するか、驚くほどです ここに別のものがあります。

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
  • この実装は、数値と文字列に対して機能します。
  • 何も書いていないので、文字列を文字配列に変換する必要はありません。
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

なぜだけではないのですか?

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

私は回文のようなだけで機能しない解決策を探していました...

  • "カヤック"
  • 「マダム」

...だけでなく...

  • 「男、計画、運河、パナマ!」
  • 「それは私が見た車または猫でしたか?」
  • 「ニクソンには「x」はありません」

反復これは優れたソリューションとして証明されています。

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

再帰的。このソリューションは、反復的なソリューションよりも悪くなることはないと思います。不要な処理を回避するために、メソッドからクリーニングステップを抽出する必要があるので、少し不安定です。

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

逆転これは高価なソリューションとして証明されています。

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

この投稿で回答し、トピックに光をもたらす人へのすべてのクレジット。


0

単語の文字ではないことを考慮する

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

ここでは、回文の数を動的にチェックできます

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、再帰的な方法が最も簡単で明確です。

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
これはすでに回答で使用されています:回文の文字列をチェック(メモ)
Tom

すみません、見逃しました。
ジョンスミス

0

ここでは、常に最初の文字から始まる、文字列内の最大の回文をチェックします。

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

コードスニペット:

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");
     }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.