Условие задачи
Нужно определить, является ли данное целое число палиндромом.
Палиндром — это число, которое читается одинаково слева направо и справа налево.
Примеры:
121→ палиндром, так как при чтении справа налево снова получится121-121→ не палиндром, так как при чтении справа налево будет121-10→ не палиндром, так как при чтении справа налево получится01, что не равно10
Формально задача звучит так:
Дано целое число
x. Вернутьtrue, если оно является палиндромом, иfalseв противном случае.
Решения через преобразование числа в строку
Одним из простых способов проверить, является ли число палиндромом, — это преобразовать его в строку и работать уже со строковым представлением. Такой подход не самый оптимальный по памяти, но позволяет быстро и наглядно решить задачу.
Решение 1: сравнение с развернутой строкой
Идея
- Преобразовать число в строку.
- Развернуть строку.
- Сравнить исходную строку и её развернутую версию.
import (
"strconv"
)
func reverseASCII(s string) string {
b := []byte(s)
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
b[i], b[j] = b[j], b[i]
}
return string(b)
}
func isPalindrome(x int) bool {
xs := strconv.Itoa(x)
xr := reverseASCII(xs)
return xs == xr
}Решение 2: посимвольное сравнение
Идея
- Преобразовать число в строку.
- Сравнивать символы с начала и конца строки, двигаясь к центру.
- Если все пары совпали — число палиндром.
import (
"strconv"
)
func isPalindromeString(s string) bool {
for i, j := 0, len(s) - 1; i < j; {
if s[i] != s[j] {
return false
}
i++
j--
}
return true
}
func isPalindrome(x int) bool {
xs := strconv.Itoa(x)
return isPalindromeString(xs)
}Решение без строкового преобразования
Хотя преобразование числа в строку делает задачу простой, можно обойтись и без этого, работая только с самим числом. Такой подход более оптимален по памяти и иногда быстрее.
Идея
- Отрицательные числа сразу исключаются (они не могут быть палиндромами из-за знака).
- Последовательно «разворачиваем» число, формируя новую переменную, куда записываются цифры в обратном порядке.
- Чтобы не разворачивать число целиком (и не рисковать переполнением), достаточно разворачивать только половину числа и сравнивать её с оставшейся половиной.
Алгоритм
- Если
x < 0или число оканчивается на0, но само не равно0, то это не палиндром. - Разворачиваем число справа налево, пока обратная половина не станет больше или равна оставшейся половине.
- Проверяем два случая:
- для чётного количества цифр обе половины должны быть равны;
- для нечётного количества цифр обратная половина без последней цифры должна быть равна оставшейся.
func isPalindrome(x int) bool {
if x < 0 || (x % 10 == 0 && x != 0) {
return false
}
reversed := 0
for x > reversed {
reversed = reversed * 10 + x % 10
x /= 10
}
return x == reversed || x == reversed/10
}Объяснение
- В цикле мы «переворачиваем» только половину числа: например, для
1221в итогеx = 12,reversed = 12. - Для нечётной длины, например
12321, получитсяx = 12,reversed = 123. Здесь последняя цифра3не влияет, поэтому сравниваемxсreversed/10. Такое решение работает заO(log10(n))по времени иO(1)по памяти.