숫자가 회문인지 어떻게 확인합니까?


127

숫자가 회문인지 어떻게 확인합니까?

모든 언어. 모든 알고리즘. (숫자를 문자열로 만든 다음 문자열을 되 돌리는 알고리즘 제외).


5
비트 단위의 정수 크기를 알 수 있습니까? 그렇다면, 말하는이며 아니요 및 S 사이즈 B = A << S / 2 [A & B == 2 ^는 S-1이면 - ^ (S / 2) + 1 2
— 니틴 Garg를

10
'숫자를 문자열로 만든 다음 문자열을 뒤집는'문제가 있습니까?
— 대령 패닉

무엇을 정의하여 시작 number및 is a palindrome방법 13E31에 대한 (기본 열을) :이 상황에서 의미한다? 01210 (제로 0)? + 10-10 + 1 (5 자리 균형 삼항)?
— greybeard

답변:


128

이것은 프로젝트 오일러 문제 중 하나입니다 . Haskell에서 해결했을 때 정확히 제안한대로 숫자를 문자열로 변환하십시오. 문자열이 pallindrome인지 확인하는 것은 사소한 일입니다. 성능이 충분하다면 왜 더 복잡하게 만드는가? pallindrome이된다는 것은 수학적인 것이 아니라 어휘 적 속성입니다.


14
과연. 모든 알고리즘은 적어도 숫자를 10 자릿수로 나누어야합니다. 어쨌든 문자열로 90 % 변환됩니다.
— Blorgbeard는 08:10

5
그것은 분명히 문자열로 변환하는 깔끔한 트릭이지만 인터뷰 에서이 질문을 받으면 요점을 이길 수 있습니다. 왜냐하면 요점은 모듈로를 이해하는지 결정하는 것이기 때문입니다.
— Robert Noack

7
@Robert Noack-면접관은 정수를 문자열로 변환하는 알고리즘을 설명하도록 요청할 수 있습니다. 물론 모듈로를 이해해야합니다.
— Steve314

@ Steve314- to describe an algorithm to convert an integer to a string, which of course requires you to understand modulo아뇨. 당신이 일반적 이진 진수로 변환하는 방법을 생각하는 (할 것입니다 추가 할 수있는 대상 번호 시스템에서 계산하는 것은 - 생각하는 데 사용되는 계산 수단 바이너리 , 당신이 할 수없는 것은 예를 들면,하지 않는 소수 연산 (당신은 할 수 할 나누기 또는 모듈로없이 2 진수에서 10 진수로 변환 2)
— greybeard

@greybeard-산술을 지원하는 유형에서 산술이 수행되고 문자열 연산은 문자열 연산을 지원하는 유형에서 수행된다고 가정합니다. 즉 문자열의 정수 및 앞에 붙는 문자에 대한 나누기와 모듈러입니다. 물론 문자열에 대해 산술을 구현할 수 는 있지만 (1) 실제로 하시겠습니까? 정수를 문자열로 변환하려면? (2)이를 사용하지 않고 (비효율적으로) 처리 할 수는 있지만 언젠가는 나머지를 이해해야합니다. 그렇지 않으면 문자열에 완전한 정수 산술이 없습니다.
— Steve314

269

주어진 숫자에 대해 :

n = num;
rev = 0;
while (num > 0)
{
    dig = num % 10;
    rev = rev * 10 + dig;
    num = num / 10;
}

만약 n == rev다음 num회문이다 :

cout << "Number " << (n == rev ? "IS" : "IS NOT") << " a palindrome" << endl;

그게 내가 함께 왔어요. 지금 게시하는 것이 의미가 없다고 생각합니다. +1
— Esteban Araya

rev가 0으로 초기화되었다고 가정합니까?
— Justsalt

그렇습니다 Justsalt. rev 변수는 0으로 초기화됩니다.
— Jorge Ferreira

31
행인에 대한 참고 사항 :num 나누기 후의 부분을 ​​유지하는 언어로 언어를 구현하는 경우 (루터 타이핑) 그렇게해야합니다 num = floor(num / 10).
— Wiseguy

22
이 솔루션은 완전히 맞지 않습니다. 변수 발굴이 넘칠 수 있습니다. 예를 들어, num 유형이 int이고 값이 거의 Integer.Max이고 마지막 숫자가 789 인 경우, 리버스 발굴을 수행 한 다음 오버플로합니다.
— Jiaji Li

24
def ReverseNumber(n, partial=0):
    if n == 0:
        return partial
    return ReverseNumber(n // 10, partial * 10 + n % 10)

trial = 123454321
if ReverseNumber(trial) == trial:
    print("It's a Palindrome!")

정수에만 작동합니다. 부동 소수점 숫자 또는 선행 0을 고려해야하는지 여부는 문제 설명에서 명확하지 않습니다.


22

사소한 문제가있는 대부분의 대답은 int 변수가 오버플로 될 수 있다는 것입니다.

http://articles.leetcode.com/palindrome-number/를 참조하십시오

boolean isPalindrome(int x) {
    if (x < 0)
        return false;
    int div = 1;
    while (x / div >= 10) {
        div *= 10;
    }
    while (x != 0) {
        int l = x / div;
        int r = x % 10;
        if (l != r)
            return false;
        x = (x % div) / 10;
        div /= 100;
    }
    return true;
}

숫자가 0이면 실패합니다. 예 : 10000021.
— Viraj

14
int is_palindrome(unsigned long orig)
{
    unsigned long reversed = 0, n = orig;

    while (n > 0)
    {
        reversed = reversed * 10 + n % 10;
        n /= 10;
    }

    return orig == reversed;
}

9

각 개별 숫자를 스택으로 밀고 튀어 나옵니다. 앞뒤로 같은 경우 회문입니다.


정수에서 각 개별 숫자를 어떻게 푸시합니까?
— Esteban Araya

1
다음과 같은 내용이 있습니다 : int firstDigit = originalNumber % 10; int tmpNumber = originalNumber / 10; int secondDigit = tmpNumber % 10; .... 끝날 때까지.
— Grant Limberg

LeetCode 질문과 관련하여 작동하지 않으므로 추가 공간이 허용되지 않습니다.
— 홀로그램

8

여분의 공간을 사용하지 않고이 문제를 해결 한 답변을 보지 못했습니다. 즉, 문자열이나 다른 정수를 사용하여 숫자를 바꾸거나 다른 데이터 구조를 사용하는 모든 솔루션을 보았습니다.

자바와 같은 언어는 정수 오버 플로우에 랩 어라운드 있지만,이 동작은 C. 같은 언어 (에 정의되지 자바 2147483647 (는 Integer.MAX_VALUE를) 반전 시도 )
해결 방법 문체, 꽤하지 않습니다, 긴 또는 무언가를 사용할 수 있지만, 할 수있다 그 접근법처럼.

회문 숫자의 개념은 숫자가 앞뒤로 동일하게 읽혀 져야한다는 것입니다. 큰. 이 정보를 사용하여 첫 번째 숫자와 마지막 숫자를 비교할 수 있습니다. 트릭은 첫 번째 숫자의 경우 순서가 필요합니다. 이것을 12321이라고 말하십시오. 이것을 10000으로 나누면 1을 얻을 수 있습니다. 후행 1은 10으로 mod를 가져 와서 검색 할 수 있습니다. 이제 이것을 232로 줄 (12321 % 10000)/10 = (2321)/10 = 232입니다. 이제 10000을 2 배로 줄여야합니다. 이제 Java 코드로 넘어갑니다.

private static boolean isPalindrome(int n) {
    if (n < 0)
        return false;

    int div = 1;
    // find the divisor
    while (n / div >= 10)
        div *= 10;

    // any number less than 10 is a palindrome
    while (n != 0) {
        int leading = n / div;
        int trailing = n % 10;
        if (leading != trailing)
            return false;

        // % with div gets rid of leading digit
        // dividing result by 10 gets rid of trailing digit
        n = (n % div) / 10;

        // got rid of 2 numbers, update div accordingly
        div /= 100;
    }
    return true;
}

숫자가 0 인 경우를 다루기 위해 Hardik 의 제안에 따라 편집했습니다 .


6

파이썬에는 빠르고 반복적 인 방법이 있습니다.

def reverse(n):
    newnum=0
    while n>0:
        newnum = newnum*10 + n % 10
        n//=10
    return newnum

def palindrome(n):
    return n == reverse(n)

또한 재귀와 관련된 메모리 문제를 방지합니다 (예 : Java의 StackOverflow 오류)


닫기,하지만이 작업을 수행하는 동안 n을 변경하고 있습니다. 원래의 n 값을 저장하고이를 대신하여 리턴 비교를 수행하려고합니다.
— RGroppa

6

내가 아는 가장 빠른 방법 :

bool is_pal(int n) {
    if (n % 10 == 0) return 0;
    int r = 0;
    while (r < n) {
        r = 10 * r + n % 10;
        n /= 10;
    }
    return n == r || n == r / 10;
}

120 (10 진수)은 "10 진수 회문"입니까? 믿을 수 없을 정도로 빠르며 eku의 답변 과 비슷합니다 .
— greybeard

5

재미로, 이것도 효과가 있습니다.

a = num;
b = 0;
if (a % 10 == 0)
  return a == 0;
do {
  b = 10 * b + a % 10;
  if (a == b)
    return true;
  a = a / 10;
} while (a > b);
return a == b;

5

숫자를 문자열로 만든 다음 문자열을 되 돌리는 것을 제외하고.

왜 그 해결책을 무시합니까? 쉽게 구현하고 읽을 수 있습니다. 컴퓨터가 없어도 2**10-23십진 회문 인지 묻는다면 십진법으로 그것을 작성하여 테스트해야합니다.

파이썬에서 적어도 '문자열 연산이 산술보다 느리다'라는 슬로건은 실제로 거짓입니다. Smink의 산술 알고리즘을 간단한 문자열 반전과 비교했습니다 int(str(i)[::-1]). 속도에는 큰 차이가 없었습니다. 문자열 반전이 약간 빨랐습니다.

컴파일 된 언어 (C / C ++)에서는 슬로건이있을 수 있지만 많은 수의 오버플로 오류가 발생할 위험이 있습니다.

def reverse(n):
    rev = 0
    while n > 0:
        rev = rev * 10 + n % 10
        n = n // 10
    return rev

upper = 10**6

def strung():
    for i in range(upper):
        int(str(i)[::-1])

def arithmetic():
    for i in range(upper):
        reverse(i)

import timeit
print "strung", timeit.timeit("strung()", setup="from __main__ import strung", number=1)
print "arithmetic", timeit.timeit("arithmetic()", setup="from __main__ import arithmetic", number=1)

초 결과 (더 낮을수록 좋음) :

중독 1.50960231881 산술 1.69729960569


4

나는 매우 무자비한 방법으로 오일러 문제에 답했다. 당연히, 새로운 잠금 해제 관련 포럼 스레드에 도착했을 때 훨씬 더 똑똑한 알고리즘이 표시되었습니다. 즉, Begoner 핸들을 지나간 멤버는 참신한 접근 방식을 사용하여 알고리즘을 사용하여 솔루션을 다시 구현하기로 결정했습니다. 그의 버전은 Python (중첩 루프 사용)이고 Clojure (단일 루프 / 반복 사용)로 다시 구현했습니다.

여기 당신의 즐거움을 위해 :

(defn palindrome? [n]
  (let [len (count n)]
    (and
      (= (first n) (last n))
      (or (>= 1 (count n))
        (palindrome? (. n (substring 1 (dec len))))))))

(defn begoners-palindrome []
  (loop [mx 0
         mxI 0
         mxJ 0
         i 999
         j 990]
    (if (> i 100)
      (let [product (* i j)]
        (if (and (> product mx) (palindrome? (str product)))
          (recur product i j
            (if (> j 100) i (dec i))
            (if (> j 100) (- j 11) 990))
          (recur mx mxI mxJ
            (if (> j 100) i (dec i))
            (if (> j 100) (- j 11) 990))))
      mx)))

(time (prn (begoners-palindrome)))

Common Lisp 답변도 있었지만 나에게 확고하지 못했습니다.


1
여기에 게시 된 "수학적"회문 테스트를 시도했지만이 문자열 기반 버전이 더 빠르다는 것에 놀랐습니다.
— Chris Vest

어쩌면 이것은 놀라운 일이 아닙니다. 결국 여러분이 회문이라는 것을 깨달을 수있는 가장 빠른 방법은 모든 종류의 산술이 아닌 상반기를 읽은 다음 후반을 거꾸로 읽는 것입니다.
— Zubin Mukerjee

4

다음은 모든 기본에 대해 작동하는 함수를 구성하는 구성표 버전입니다. 중복 검사 기능이 있습니다. 숫자가 기수의 배수이면 신속하게 false를 반환합니다 (0으로 끝남).
그리고 전체 역수를 다시 만들지 않고 절반 만 만듭니다.
그게 우리가 필요한 전부입니다.

(define make-palindrome-tester
   (lambda (base)
     (lambda (n)
       (cond
         ((= 0 (modulo n base)) #f)
         (else
          (letrec
              ((Q (lambda (h t)
                    (cond
                      ((< h t) #f)
                      ((= h t) #t)
                      (else
                       (let*
                           ((h2 (quotient h base))
                            (m  (- h (* h2 base))))
                         (cond
                           ((= h2 t) #t)
                           (else
                            (Q h2 (+ (* base t) m))))))))))
            (Q n 0)))))))

4

숫자를 문자열로 변환하지 않고 루비의 재귀 솔루션.

def palindrome?(x, a=x, b=0)
  return x==b if a<1
  palindrome?(x, a/10, b*10 + a%10)
end

palindrome?(55655)

3

골랑 버전 :

package main

import "fmt"

func main() {
    n := 123454321
    r := reverse(n)
    fmt.Println(r == n)
}

func reverse(n int) int {
    r := 0
    for {
        if n > 0 {
            r = r*10 + n%10
            n = n / 10
        } else {
            break
        }
    }
    return r
}

2

첫 번째와 마지막 숫자를 튀어 나와 다 떨어질 때까지 비교하십시오. 남은 자릿수가있을 수도 있지만 아닐 수도 있습니다. 단, 팝된 자릿수가 모두 일치하면 회문입니다.


2

다음은 템플릿을 사용하는 C ++의 솔루션입니다. 이 솔루션은 대소 문자를 구분하지 않는 회문 문자열 비교에 사용할 수 있습니다.

template <typename bidirection_iter>
bool palindrome(bidirection_iter first, bidirection_iter last)
{
    while(first != last && first != --last)
    {
        if(::toupper(*first) != ::toupper(*last))
            return false;
        else
            first++;
    }
    return true;
}

1

@sminks 방법보다 약간 더 일정한 상수를 가진 방법 :

num=n
lastDigit=0;
rev=0;
while (num>rev) {
    lastDigit=num%10;
    rev=rev*10+lastDigit;
    num /=2;
}
if (num==rev) print PALINDROME; exit(0);
num=num*10+lastDigit; // This line is required as a number with odd number of bits will necessary end up being smaller even if it is a palindrome
if (num==rev) print PALINDROME

1

다음은 af # 버전입니다.

let reverseNumber n =
    let rec loop acc = function
    |0 -> acc
    |x -> loop (acc * 10 + x % 10) (x/10)    
    loop 0 n

let isPalindrome = function
    | x  when x = reverseNumber x -> true
    | _ -> false

1

문자열 표현이 palindromic 인 경우 숫자는 palindromic입니다.

def is_palindrome(s):
    return all(s[i] == s[-(i + 1)] for i in range(len(s)//2))

def number_palindrome(n):
    return is_palindrome(str(n))

1
def palindrome(n):
    d = []
    while (n > 0):
        d.append(n % 10)
        n //= 10
    for i in range(len(d)/2):
        if (d[i] != d[-(i+1)]):
            return "Fail."
    return "Pass."

1

주어진 숫자가 Palindrome인지 아닌지 확인하려면 (Java Code)

class CheckPalindrome{
public static void main(String str[]){
        int a=242, n=a, b=a, rev=0;
        while(n>0){
                    a=n%10;  n=n/10;rev=rev*10+a;
                    System.out.println(a+"  "+n+"  "+rev);  // to see the logic
               }
        if(rev==b)  System.out.println("Palindrome");
        else        System.out.println("Not Palindrome");
    }
}

1

여기에 게시 된 많은 솔루션은 정수를 뒤집어 추가 공간 인을 사용하는 변수에 저장 O(n)하지만 여기에는 O(1)공간 이있는 솔루션이 있습니다.

def isPalindrome(num):
    if num < 0:
        return False
    if num == 0:
        return True
    from math import log10
    length = int(log10(num))
    while length > 0:
        right = num % 10
        left = num / 10**length
        if right != left:
            return False
        num %= 10**length
        num /= 10
        length -= 2
    return True

1

나는 컴팩트하기 때문에 항상이 파이썬 솔루션을 사용합니다.

def isPalindrome(number):
    return int(str(number)[::-1])==number

4
즉 소형이지만, 영업 이익은 특히 "며 문자열을 반전 한 후 숫자를 문자열을 만드는 및 알고리즘 제외 "
— 에드워드

0

이 시도:

reverse = 0;
    remainder = 0;
    count = 0;
    while (number > reverse)
    {
        remainder = number % 10;
        reverse = reverse * 10 + remainder;
        number = number / 10;
        count++;
    }
    Console.WriteLine(count);
    if (reverse == number)
    {
        Console.WriteLine("Your number is a palindrome");
    }
    else
    {
        number = number * 10 + remainder;
        if (reverse == number)
            Console.WriteLine("your number is a palindrome");
        else
            Console.WriteLine("your number is not a palindrome");
    }
    Console.ReadLine();
}
}

0

다음은 파이썬에서 목록을 스택으로 사용하는 솔루션입니다.

def isPalindromicNum(n):
    """
        is 'n' a palindromic number?
    """
    ns = list(str(n))
    for n in ns:
        if n != ns.pop():
            return False
    return True

스택을 터뜨리면 비교를 위해 숫자의 가장 오른쪽 만 고려하고 검사를 줄이는 데 실패합니다.


0
 public class Numbers
 {
   public static void main(int givenNum)
   { 
       int n= givenNum
       int rev=0;

       while(n>0)
       {
          //To extract the last digit
          int digit=n%10;

          //To store it in reverse
          rev=(rev*10)+digit;

          //To throw the last digit
          n=n/10;
      }

      //To check if a number is palindrome or not
      if(rev==givenNum)
      { 
         System.out.println(givenNum+"is a palindrome ");
      }
      else
      {
         System.out.pritnln(givenNum+"is not a palindrome");
      }
  }
}

0
let isPalindrome (n:int) =
   let l1 = n.ToString() |> List.ofSeq |> List.rev
   let rec isPalindromeInt l1 l2 =
       match (l1,l2) with
       | (h1::rest1,h2::rest2) -> if (h1 = h2) then isPalindromeInt rest1 rest2 else false
       | _ -> true
   isPalindromeInt l1 (n.ToString() |> List.ofSeq)

0
checkPalindrome(int number)
{
    int lsd, msd,len;
    len = log10(number);
    while(number)
    {
        msd = (number/pow(10,len)); // "most significant digit"
        lsd = number%10; // "least significant digit"
        if(lsd==msd)
        {
            number/=10; // change of LSD
            number-=msd*pow(10,--len); // change of MSD, due to change of MSD
            len-=1; // due to change in LSD
            } else {return 1;}
    }
    return 0;
}

나쁜 해결책. Log10은 정말 느린 부동 소수점 연산입니다. 이것을 사용하지 마십시오.
— Rok Kralj

0

매우 효율적이지 않은 재귀 방식은 옵션을 제공합니다.

(파이썬 코드)

def isPalindrome(num):
    size = len(str(num))
    demoninator = 10**(size-1)
    return isPalindromeHelper(num, size, demoninator)

def isPalindromeHelper(num, size, demoninator):
    """wrapper function, used in recursive"""
    if size <=1:
        return True
    else:       
        if num/demoninator != num%10:
            return False
        # shrink the size, num and denominator
        num %= demoninator
        num /= 10
        size -= 2
        demoninator /=100
        return isPalindromeHelper(num, size, demoninator) 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.