회문에 대한 문자열 확인


93

회문는 단어, 문장, 숫자 또는 어느 한 방향으로 동일한 방식으로 읽을 수있는 장치의 다른 서열이다.

단어가 회문인지 확인하기 위해 단어의 문자 배열을 가져와 문자를 비교합니다. 나는 그것을 테스트했고 작동하는 것 같습니다. 그러나 나는 그것이 옳은지 또는 개선해야 할 것이 있는지 알고 싶습니다.

내 코드는 다음과 같습니다.

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
확실하지이 의도적하지만 예에서 문자열 경우 - reliefpfpfeiller이 - 회문 아니다
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 루프의 조건이 더 이상 참이 아니므로 루프가 종료되고 참을 반환합니다.


1
사전 증가 (++ i1 및 -i2) 대신 사후 증가 (i1 ++, i2--)를 사용할 수도 있습니다.
user0946076422 2015-08-15

@ 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 2014

2
@FernandoPelliccioni, 다른 솔루션과 동일한 복잡성이라고 생각합니다.
aioobe

1
@Fernando, 내가 말할 수있는 한 모든 답변은 선형 복잡성을 가지고 있습니다. 이 때문에 어떤 솔루션이 가장 효율적인지에 대한 확실한 답을 제공 할 방법이 없습니다. 벤치 마크를 실행할 수 있지만 특정 JVM 및 JRE에 따라 다릅니다. 블로그 게시물에 행운을 빕니다. 그것을 읽을 것을 고대하고 있습니다.
aioobe

1
@FernandoPelliccioni 똑똑하고 영리하며 어려운 상황에 대한 해결책을 찾을 수있는 사람을위한 관용구입니다. :-)
Sipty

1
@FernandoPelliccioni 좋은 분석
Saravana

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

또는 recursion .

더 짧은 재귀 솔루션을 찾고있는 사람은 주어진 문자열이 회문으로 만족하는지 확인합니다.

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

2
더 짧은 버전을 단순화 할 수 있습니다.return s.charAt(0) == s.charAt(l - 1) && isPalindrome(s.substring(1, l - 1));
vault

10

Go, 자바 :

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 2019

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는 모든 문자열 절반 길이 TIL 인덱스 다음 처음부터 끝까지에서을 비교 한 작업이 완료를 제공합니다.

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

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"?
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

이 질문의 중복으로 표시된 질문에 대한 해결책을 연구했습니다. 여기에 던져 버릴지도 몰라 ...

질문은이 문제를 해결하기 위해 한 줄을 요구했고, 저는 그것을 문학 회문으로 더 많이 사용했습니다. 따라서 공백, 구두점 및 대 / 소문자가 결과를 버릴 수 있습니다.

다음은 작은 테스트 클래스가있는 추악한 솔루션입니다.

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. 문자열이 문자가 없거나 하나의 문자로 이루어진 경우 회문입니다.
  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 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
이 접근 방식은 훌륭합니다. 시간 복잡도 O (n), 공간 복잡도 O (1)
kanaparthikiran

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

복잡성 : 선형 시간,

  • 내가 RandomAccessIterator 인 경우 : floor (n / 2) 비교 및 ​​floor (n / 2) * 2 반복

  • 내가 BidirectionalIterator 인 경우 : floor (n / 2) 비교 및 ​​floor (n / 2) * 2 반복 + (3/2) * n 반복을 더하여 중간 (middle function)

  • 저장 : 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

죄송합니다. 놓쳤습니다.
john Smith

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.