如何检查一个数字是否是回文数字?

如何检查一个数字是否是回文数字?

任何语言。 任何algorithm。 (除了使数字成为string然后反转string的algorithm)。

这是项目欧拉问题之一 。 当我在Haskell中解决这个问题时,我完全按照你的build议,把这个数字转换成一个String。 然后检查string是否是一个晦涩难懂的小事。 如果性能足够好,那么为什么要把它变得更复杂呢? 作为一个pallindrome是一个词汇属性,而不是一个math的。

对于任何给定的数量:

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

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

以上大多数有一个微不足道的问题的答案是intvariables可能会溢出。

请参阅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; } 
 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; } 

将每个单独的数字推入堆栈,然后将其popup。 如果前后相同,则是回文。

除了让一个string的数字,然后扭转string。

为什么解雇这个解决scheme? 这很容易实现和可读 。 如果问你手边没有电脑是否2**10-23是十进制回文,你一定要用十进制来写出来。

至less在Python中,“string操作比算术慢”的口号实际上是错误的。 我将Smink的算术algorithm与简单string反转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

我没有注意到任何解决这个问题的答案,没有额外的空间,也就是说,我看到的所有解决scheme使用了一个string,或另一个整数来反转数字,或一些其他数据结构。

虽然像Java这样的语言环绕整数溢出,这种行为是未定义的像C语言[ 尝试在Java中颠倒2147483647(Integer.MAX_VALUE) ]解决方法可能是使用一个很长的东西,但在风格上,我不太就像那样

现在,回文数字的概念是这个数字应该是前后相同的。 大。 使用这个信息,我们可以比较第一个数字和最后一个数字。 窍门是,第一个数字,我们需要的数量的顺序。 如果将这个数字除以10000,我们就可以得到领先的1.后面的1可以通过取10来得到。现在,把它减less到232. (12321 % 10000)/10 = (2321)/10 = 232 。 而现在,10000将需要减less2倍。所以,现在的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; } 

我用一种非常暴躁的方式回答了欧拉问题。 当然,当我到达新的未locking的相关论坛线程时,显示中有一个更聪明的algorithm。 也就是说,一个经过Begoner处理的成员有一个新颖的方法,我决定用他的algorithm重新实现我的解决scheme。 他的版本是在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 (* ij)] (if (and (> product mx) (palindrome? (str product))) (recur product ij (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的答案,但是对我来说是无法解决的。

只是为了好玩,这个也适用。

 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; 

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

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

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

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

这也可以防止recursion的内存问题(如Java中的StackOverflow错误)

我知道最快的方法:

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

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 } 

在ruby的recursion解决scheme,没有把数字转换成string

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

popup的第一个和最后一个数字,并比较它们,直到你用完。 可能还有一个数字,或者不是,但是无论哪种方式,如果所有popup的数字匹配,这是一个回文。

这里是使用模板的c ++中的另一个解决scheme。 此解决scheme将适用于不区分大小写的回文string比较。

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

一个比@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 

这里是#版本:

 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 

如果一个数字的string表示是回文的,则它是回文的:

 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)) 
 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." 

要检查给定的数字是否是回文(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"); } } 

这里发布的很多解决scheme都将整数反转,并将其存储在一个使用额外空间的variables中,这个空间是O(n) ,但是这里有一个O(1)空间的解决scheme。

 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 

由于其紧凑性,我总是使用这个python解决scheme。

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

尝试这个:

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

这里是一个解决scheme在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 

popup堆栈只考虑数字的最右边进行比较,并且快速失败以减less检查

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

recursion方式,效率不高,只是提供一个选项

(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)