30 ответов:
Это одна из проблем проекта Эйлера. Когда я решил в Haskell я сделал именно то, что вы предлагаете, преобразовать число в строку. Тогда тривиально проверить, что строка является паллиндромом. Если он работает достаточно хорошо, то зачем беспокоиться о том, чтобы сделать его более сложным? Быть паллиндромом-это скорее лексическое свойство, чем математическое.
для любого заданного числа:
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!")работает только для целых чисел. Из постановки задачи неясно, нужно ли учитывать числа с плавающей запятой или ведущие нули.
выше большинства ответов, имеющих тривиальную проблему, заключается в том, что переменная 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; }
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; }
нажмите каждую отдельную цифру в стек, а затем вытащите их. Если это то же самое вперед и назад, это палиндром.
Я не заметил никаких ответов, которые решали эту проблему, не используя дополнительного пространства, т. е. все решения, которые я видел, либо использовали строку, либо другое целое число для обратного числа, либо некоторые другие структуры данных.
хотя языки, такие как Java, обертываются при переполнении целых чисел, это поведение не определено в таких языках, как C. [попробуйте повернуть вспять 2147483647 (целое число.MAX_VALUE) в Java] Обходной путь может быть использовать длинный или что-то еще, но стилистически мне это не совсем нравится подход.
(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; }отредактировано согласно Хардик's, чтобы покрыть случаи, когда есть нули в количестве.
за исключением того, чтобы сделать число строкой,а затем перевернуть строку.
зачем отвергать это решение? это легко реализовать и читабельный. Если вас спросили без компьютера под рукой ли
2**10-23- это десятичный палиндром, вы наверняка проверите его, записав его в десятичном формате.по крайней мере, в Python лозунг "строковые операции медленнее, чем арифметика" на самом деле ложен. Я сравнил арифметический алгоритм Сминка с простым разворот строки
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
в 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)Это также предотвращает проблемы с памятью с рекурсией (например, ошибка StackOverflow в Java)
Я ответил на проблему Эйлера, используя очень грубый способ. Естественно, был гораздо более умный алгоритм на дисплее, когда я добрался до Нового разблокированного связанного потока форума. А именно, у члена, который пошел по ручке 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)))были также общие ответы на шепелявость, но они были для меня недоступны.
просто для удовольствия, это тоже работает.
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;
вот вариант схемы, которая создает функцию, которая будет работать против любой базы. Он имеет проверку избыточности: быстро возвращает 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)))))))
самый быстрый способ, который я знаю:
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, без преобразования числа в строку
def palindrome?(x, a=x, b=0) return x==b if a<1 palindrome?(x, a/10, b*10 + a%10) end palindrome?(55655)
поп от первой и последней цифры и сравнить их, пока вы не закончите. Там может быть цифра слева, или нет, но в любом случае, если все выскочили цифры совпадают, это палиндром.
вот еще одно решение в 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; }
метод с немного лучшим постоянным фактором, чем метод @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
вот версия 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
число является палиндромом, если его строковое представление является палиндромом:
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)
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"); } }
многие решения, опубликованные здесь, переворачивают целое число и сохраняют его в переменной, которая использует дополнительное пространство, которое
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
Я всегда использую это решение python из-за его компактности.
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(); } }
вот список использования решений в виде стеков в 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выталкивание стека учитывает только самую правую сторону числа для сравнения, и он не может быстро уменьшить проверки
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; }
рекурсивный способ, не очень эффективный, просто предоставить возможность
(код на 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)
Comments