题目描述
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数
是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
示例
示例 1:
输入:x = 121
输出:true
示例 2:输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。
解题
解法一: 转化为字符串反向切片
思路
把整数转换成字符串,然后进行反向切片,从而实现了反转。最后再比对是否相等,即可。
算法复杂度
时间复杂度:O(n),其中 n 是输入整数 x 的位数。
转换为字符串的时间复杂度大致为 O(n),因为需要遍历每一位并将其转换为字符。
获取反向字符串的时间复杂度也为 O(n)。
比较字符串是否相等:时间复杂度为 O(1)。
综上所述:根据加法法则,总的时间复杂度等于各步骤中最耗时的部分,即 O(n)。因此,该实现的时间复杂度为 O(n),其中 n 是输入整数 x 的位数。
空间复杂度:O(n),其中 n 是输入整数 x 的位数。
字符串存储:在将整数 x 转换为字符串时,需要创建一个新的字符串对象来存储转换结果。字符串的长度与整数 x 的位数相同,即 n。因此,这部分的空间复杂度为 O(n)。
反向字符串:这部分的空间复杂度为 O(1)。
综上所述:故该实现的空间复杂度为 O(n),其中 n 是输入整数 x 的位数。
代码
class Solution:
def isPalindrome(self, x: int) -> bool:
return str(x)==str(x)[::-1]
解法二:直接对整数进行数学操作
思路
循环逐个取出整数的低位数字,并添加到反转部分 reversed_part 中,直到处理完整数x,然后再比对reversed_part是否与整数x相等。
利用:%10来取原始整数的最低位,//10 去掉原始整数已处理的最低位数字。
算法复杂度
时间复杂度:O(n),其中 n 是输入整数 x 的位数。
整个函数的时间复杂度主要由循环决定,为 O(n),其中 n 是输入整数 x 的位数。
空间复杂度:O(1),常数空间存放若干变量。
代码
class Solution:
def isPalindrome(self, x: int) -> bool:
# 如果是负数,肯定不是回文数,直接返回False
if x < 0:
return False
# 初始化反转部分
reversed_part = 0
# 用于存储原始整数除以10后的余数
original_num = x
while original_num > 0:
remainder = original_num % 10 # 取出最低位
# 实现最先取出的最低位,始终排在前面
reversed_part = (reversed_part * 10) + remainder
original_num //= 10 # 去除掉已经取出的最低位
# 反转结果是否等于原始整数
return original_num == 0 and reversed_part == x
算法优化
思路
回文数,正序和逆序都是一样的,所以可以考虑只处理一半,可以进一步减少计算。
那么在此算法的基础上,如何确定处理了一半的整数呢?
假设当前原始数字是回文数的基础上,当原始整数小于或等于反转后的数字时,就是已经处理到一半了。
如果该原始整数不是回文数,利用上面说的条件,有可能会多处理,不是处理一半,但是这个不是重点,例如:如果是5423,最后就是return 5==324 or 5==32。因为多处理了,最后剩余的原始整数和反转的结果肯定也没法相等。
在判断为负数的基础上还可以进一步筛选处理无效的数字:如果该整数不是0,而最低位为0。那也不是回文数,因为第一位数字不会是0。
算法复杂度
时间复杂度: O(n),其中 n 是输入整数 x 的位数。
对于偶数位整数,循环次数接近一半;对于奇数位整数,循环次数略大于一半。总体来看,循环次数大致为整数位数的一半,因此时间复杂度还是为 O(n),其中 n 是输入整数 x 的位数。
空间复杂度:O(1),常数空间存放若干变量。
代码
class Solution:
def isPalindrome(self, x: int) -> bool:
# 如果是负数,肯定不是回文数,直接返回False
# 个位为0但本身不是0的数,因为第一位数不会是0,而最后一位数为0,肯定不是回文数
if x < 0 or (x != 0 and x % 10 == 0):
return False
# 初始化反转部分
reversed_part = 0
# 用于存储原始整数除以 10 后的余数
original_num = x
# 假设原始数字是回文数的基础上
# 当原始数字大于反转后的数字时,说明还没有处理到一半
while original_num > reversed_part:
remainder = original_num % 10
reversed_part = (reversed_part * 10) + remainder
original_num //= 10
# 如果整数是偶数位,则反转结果刚好可以等于原始整数数剩下的一半
# 如果是奇数,反转结果会比原始整数剩下的一半多一位,所以反转结果在比较时要再去除掉一位
return original_num == reversed_part or original_num == reversed_part // 10
注意事项
上述优化的代码,在进行反转一半处理前,一定要先排除待判断整数的个位为0的情况(x != 0 and x % 10 == 0),不然在处理最低位为0的情况下,会出错误哦~~~