题目
地址
https://leetcode.com/problems/palindrome-number/description/
内容
Given an integer x, return true if x is a palindrome, and false otherwise.
Example 1:
Input: x = 121
Output: true
Explanation: 121 reads as 121 from left to right and from right to left.
Example 2:
Input: x = -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.
Example 3:
Input: x = 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.
Constraints:
- -231 <= x <= 231-1
Follow up: Could you solve it without converting the integer to a string?
解题
这题就是要求不使用字符串的方式,判断一个数在10进制表示时是否是个回文数。
因为这个是10进制数的逐位比较,不能使用诸如左移右移之类的操作来简化运算,只能使用对10取模以及除以10这样的操作来取各个位置的数字。
一种比较简单的思路是将10进制的每位保存到一个容器(如vector)中,然后从容器头部和尾部逐位对比。
bool isPalindrome(int x) {
if (x < 0) {
return false;
}
std::vector<int> v;
while (x != 0) {
v.push_back(x % 10);
x /= 10;
}
int left = 0;
int right = v.size() - 1;
while (left < right) {
if (v[left] != v[right]) {
return false;
}
left++;
right--;
}
return true;
}
这个方法比较传统,但是有一个问题,就是它的遍历次数略多。
如果我们希望减少遍历次数,又不想引入其他运算,只要能识别出数字的中间位置,然后逐位对比即可。
bool isPalindrome(int x) {
int count = 0;
if (x >= 0 && x < 10) {
return true;
} else if (x >= 10 && x < 100) {
count = 2;
} else if (x >= 100 && x < 1000) {
count = 3;
} else if (x >= 1000 && x < 10000) {
count = 4;
} else if (x >= 10000 && x < 100000) {
count = 5;
} else if (x >= 100000 && x < 1000000) {
count = 6;
} else if (x >= 1000000 && x < 10000000) {
count = 7;
} else if (x >= 10000000 && x < 100000000) {
count = 8;
} else if (x >= 100000000 && x < 1000000000) {
count = 9;
} else if (x >= 1000000000 && x < 2147483648) {
count = 10;
} else {
return false;
}
int pushCount = count / 2;
int popCount = pushCount;
stack<int> s;
while (pushCount > 0) {
s.push(x % 10);
x /= 10;
pushCount--;
}
// 奇数位则抛弃中间的数字
if (count % 2 != 0) {
x /= 10;
}
while (popCount > 0) {
if (s.top() != x % 10) {
return false;
}
s.pop();
x /= 10;
popCount--;
}
return true;
}
上面这个算法就是将回文数右侧数字Push到栈中,然后陆续Pop出数字,和左侧数字从后向前对比。这个算法需要引入寻找中间位置的逻辑,且显得略复杂。
最后一种不需要计算中间位置,同时遍历次数相对比较少的是:利用原数字的低位构建新的数字的高位,然后对比两个数字是否相同。
bool isPalindrome(int x) {
if (x < 0) {
return false;
}
long long reverse = 0;
int original = x;
while (x != 0) {
reverse = reverse * 10 + x % 10;
x /= 10;
}
return reverse == original;
}
这个方法非常简单,但是会引入乘法操作。
代码地址
https://github.com/f304646673/leetcode/tree/main/9-Palindrome-Number/cplusplus