算法:回文数
题目
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
- 例如,
121是回文,而123不是。
示例 1:
1 | 输入:x = 121 |
示例 2:
1 | 输入:x = -121 |
示例 3:
1 | 输入:x = 10 |
提示:
-231 <= x <= 231 - 1
**进阶:**你能不将整数转为字符串来解决这个问题吗?
解法
1 | func isPalindrome(_ x: Int) -> Bool { |
我们来详细分析一下这个算法的每个步骤:
1. 排除负数和尾部为零的情况
1 | if x < 0 || (x != 0 && x % 10 == 0) { |
负数不能是回文数,因为负号只会出现在数字的前面,不可能出现在数字的后面。
如果数字以
0结尾,且数字不为0本身,那么它也不能是回文数。例如,10和100等数字就不能是回文数,因为它们反过来就不会是有效的数字。
因此,首先排除负数和尾部为零的非零数字。
2. 初始化变量
1 | var p = x |
p是我们用来操作输入数字的变量,初始值为x。n是我们用来构建数字反转部分的变量,初始值为0。
3. 反转数字的后半部分
1 | while p > n { |
这里使用
while p > n作为条件,表示我们会反转数字的后半部分直到它大于或等于数字的前半部分。这个操作的目的是让n变成数字x的后半部分的反转,而p逐渐变成前半部分。在每次迭代中:
n = n * 10 + p % 10:把p的最后一位数字加到n的末尾,构建反转后的数字n。p /= 10:将p向右移一位,即去掉p的最后一位。
通过这个过程,n 将逐渐成为 x 的后半部分的反转,p 将逐渐成为 x 的前半部分。
4. 判断回文条件
1 | return n == p || n / 10 == p |
一旦
p小于或等于n,表示我们已经处理完了数字的一半。此时有两个情况:如果
n == p,表示前半部分和后半部分完全相等,数字是回文数。如果
n / 10 == p,表示n有一个额外的数字(例如奇数位的中间数字),通过去掉这个多余的数字(即n / 10),我们得到的值与p相等,数字仍然是回文数。
举个例子:
对于
121:首先
n会变成12,p变成1,然后退出循环。此时
n / 10等于1,p也是1,所以返回true。
对于
123:首先
n会变成32,p变成1,然后退出循环。n / 10等于3,p是1,结果是false。
总结:
这个算法通过反转数字的后半部分来判断数字是否为回文。我们只需要将数字的一半反转,然后比较两部分是否相等。
时间复杂度:
O(log₁₀(x)),因为我们每次都在处理x的一位数字,直到处理到一半。空间复杂度:
O(1),只用了常量空间。