代码之家  ›  专栏  ›  技术社区  ›  Esteban Araya

如何检查数字是否为回文?

  •  120
  • Esteban Araya  · 技术社区  · 16 年前

    如何检查数字是否为回文?

    任何语言。任何算法。(除了将数字变为字符串然后反转字符串的算法)。

    49 回复  |  直到 6 年前
        1
  •  119
  •   Dan Dyer    16 年前

    这是 one of the Project Euler problems . 当我用haskell解决它时,我按照你的建议做了,把数字转换成一个字符串。然后检查一下绳子是否是一个帕林罗马。如果它的性能足够好,那为什么还要让它更复杂呢?作为一个苍白的罗马是一个词汇属性而不是一个数学属性。

        2
  •  260
  •   ani627    10 年前

    对于任何给定的数字:

     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;
    
        3
  •  24
  •   Mark Ransom    8 年前
    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!")
    

    仅适用于整数。问题陈述中不清楚是否需要考虑浮点数或前导零。

        4
  •  20
  •   Jiaji Li    11 年前

    最重要的是,有一个小问题的答案是int变量可能溢出。

    参照 http://leetcode.com/2012/01/palindrome-number.html

    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;
    }
    
        5
  •  14
  •   Robert Gamble    16 年前
    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;
    }
    
        6
  •  9
  •   Grant Limberg    16 年前

    将每个数字推到一个堆栈上,然后将其弹出。如果前后都一样,那就是回文。

        7
  •  8
  •   timokratia Debosmit Ray    7 年前

    我没有注意到有任何答案可以不用额外的空间来解决这个问题,也就是说,我看到的所有解决方案要么使用一个字符串,要么使用另一个整数来反转数字,要么使用其他一些数据结构。

    虽然像Java这样的语言在整数溢出上缠绕,但这种行为在C语言中是未定义的。 在爪哇中尝试反转2147483647(整数.Max值) ] 解决方法可能是使用一个长的或其他的东西,但在风格上,我不太喜欢这种方法。

    现在,回文数的概念是,这个数应该向前和向后读相同的数。伟大的。利用这些信息,我们可以比较第一个数字和最后一个数字。诀窍是,对于第一个数字,我们需要数字的顺序。比如说,12321。将这个除以10000,我们将获得第一名。尾随的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;
    }
    

    按要求编辑 Hardik 关于数字中有零的情况的建议。

        8
  •  6
  •   rassa45    6 年前

    在Python中,有一种快速、迭代的方法。

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

    这也防止了递归的内存问题(比如爪哇的StAcExpRoad错误)

        9
  •  5
  •   Colonel Panic    12 年前

    除了将数字变为字符串然后反转字符串。

    为什么不考虑这个解决方案? 它易于实现和可读 . 如果有人问你手头没有电脑 2**10-23 是一个十进制回文,你肯定会用十进制来测试它。

    至少在Python中,“字符串操作比算术慢”的口号实际上是错误的。我将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

        10
  •  4
  •   Chris Vest    16 年前

    我用一种非常残忍的方式回答了欧拉问题。当然,当我进入新的未锁定的关联论坛线程时,在显示中有一个更聪明的算法。也就是说,一个经过handle-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)))
    

    也有一些常见的口齿不清的答案,但对我来说它们是不可接受的。

        11
  •  4
  •   Toon Krijthe    16 年前

    只是为了好玩,这个也行。

    a = num;
    b = 0;
    while (a>=b)
    {
      if (a == b) return true;
      b = 10 * b + a % 10;
      if (a == b) return true;
      a = a / 10;
    }
    return false;
    
        12
  •  4
  •   Mark Bolusmjak    15 年前

    这里有一个方案版本,它构造了一个对任何基都有效的函数。它有一个冗余检查:如果数字是基数的倍数(以0结尾),则快速返回false。 它不会重建整个倒数,只有一半。这就是我们所需要的。

    (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)))))))
    
        13
  •  4
  •   Flowers    9 年前

    我知道最快的方法:

    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;
    }
    
        14
  •  3
  •   Thomas Modeneis    9 年前

    Golang版本:

    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
    }
    
        15
  •  3
  •   dre-hh    9 年前

    Ruby中的递归解决方案,不将数字转换为字符串

    def palindrome?(x, a=x, b=0)
      return x==b if a<1
      palindrome?(x, a/10, b*10 + a%10)
    end
    
    palindrome?(55655)
    
        16
  •  2
  •   Eli    16 年前

    弹出第一个和最后一个数字,并进行比较,直到用完为止。可能还有一个数字,或者没有,但是不管怎样,如果所有弹出的数字都匹配,那就是回文。

        17
  •  2
  •   VikramChopde    10 年前

    这里是使用模板的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;
    }
    
        18
  •  1
  •   eku    13 年前

    常数因子比@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
    
        19
  •  1
  •   Omu    12 年前

    以下是F版本:

    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
    
        20
  •  1
  •   hughdbrown    12 年前

    如果数字的字符串表示形式是回文形式,则该数字是回文形式:

    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))
    
        21
  •  1
  •   Rock    12 年前
    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."
    
        22
  •  1
  •   sort_01out    10 年前

    检查给定的数字是否回文(Java代码)

    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");
        }
    }
    
        23
  •  1
  •   0x0    10 年前

    这里发布的许多解决方案都会反转整数,并将其存储在一个变量中,该变量使用了额外的空间,即 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
    
        24
  •  1
  •   user2343020    10 年前

    我总是使用这个python解决方案,因为它很紧凑。

    def isPalindrome(number):
        return int(str(number)[::-1])==number
    
        25
  •  0
  •   bool.dev    12 年前

    试试这个:

    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();
    }
    }
    
        26
  •  0
  •   lwm    11 年前

    下面是一个在python中使用列表作为堆栈的解决方案:

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

    弹出堆栈只考虑用于比较的数字的最右边,它无法快速减少检查

        27
  •  0
  •   BLaaaaaa    11 年前
     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");
          }
      }
    }
    
        28
  •  0
  •   mario    11 年前
    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)
    
        29
  •  0
  •   MarianG    11 年前
    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;
    }
    
        30
  •  0
  •   user1552891    11 年前

    递归方式,不是很有效,只提供一个选项

    (Python代码)

    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)