力扣:9.回文数の题解
大家好,我是Zac!马上就到10月24日了,那可是是我们程序员的节日!好久不发题解了,那今天我们就爽一波,发一道力扣的题解!
T1:回文数
题目传送门:传送!
题目描述
给你一个整数 x
,如果 x
是一个回文整数,返回 true
;否则,返回 false
。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
- 例如,
121
是回文,而123
不是。
示例 1:
输入:x = 121 输出:true
示例 2:
输入:x = -121 输出:false 解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入:x = 10 输出:false 解释:从右向左读, 为 01 。因此它不是一个回文数。
提示:
-2^31 <= x <= 2^31 - 1
进阶:你能不将整数转为字符串来解决这个问题吗?(不能)
解题思路(字符串版)
这道题在这种做法下是一道水题,只要你找到方法。
我们先分析一下给的默认代码:
class Solution {
public:bool isPalindrome(int x) {}
};
可以发现,题目给了一个int
类型的变量?好吧,我无语了😑,题目说是 :-2^31 <= x <= 2^31 - 1,但你给了一个int?那就按照你的这个int来做吧!
解法一:字符串反转法
分析题目:回文数的核心特征就是正着读和反着读一样。既然数字可以当作字符串处理,那直接反转字符串比较岂不美哉?
提出假设:把整数转成字符串,反转后如果和原字符串相同,就是回文数。
验证假设:
-
121 → "121" → 反转"121" → 相同 ✓
-
-121 → "-121" → 反转"121-" → 不同 ✓
-
10 → "10" → 反转"01" → 去除前导0→得到不同 ✓
得出结论:字符串反转法简单粗暴有效,就是有点"作弊"嫌疑——题目明明说是整数,我们却偷偷转成了字符串(好像没说不行哈?)
直接给我上代——码!
AC Code:
class Solution {
public:bool isPalindrome(int x) {string a = to_string(x);string b = a;reverse(b.begin(), b.end());for (int i = 0; i < a.size(); i++) {if (a[i] != b[i]) {return false;}}return true;}
};
class Solution {
public:bool isPalindrome(int x) {string a = to_string(x); // 转换为stringstring b = a; // 赋值,方便后面的反转判断reverse(b.begin(), b.end()); // 反转for (int i = 0; i < a.size(); i++) { // 判断是否一样if (a[i] != b[i]) {return false; }}return true;}
};
class Solution {
public:bool isPalindrome(int x) {string a=to_string(x);string b=a;reverse(b.begin(),b.end());for(int i =0;i<a.size();i++){if(a[i]!=b[i]) return false;}return true;}
};
class Solution {
public:bool isPalindrome(int x) {string a=to_string(x); // 转换为stringstring b=a; // 赋值,方便后面的反转判断reverse(b.begin(),b.end()); // 反转for(int i =0;i<a.size();i++){ // 判断反转后是否一样if(a[i]!=b[i]) return false;}return true;}
};
解法二:字符串双指针
解题思路:回文就是首尾对称,那何必整个反转?从两头往中间比较就行了,发现不对劲立马开溜!
分析代码:题目还是给那个int,看来是铁了心要我们处理整数。不过我们可以继续"作弊"转字符串。
提出假设:用两个指针从字符串两端向中间移动,逐个比较字符,不一样就直接返回false。
验证假设:
-
121:左'1'=右'1' → 左'2'=右'2' → 成功 ✓
-
123:左'1'=右'3'?不相等 → 立即返回false ✓
-
-121:第一个字符'-'和最后一个字符'1'就不一样 → 直接false ✓
得出结论:双指针法比完全反转更聪明,发现不匹配就能提前退出,效率更高,而且代码写起来很酷!
直接给我上代——码!
AC Code:
class Solution {
public:bool isPalindrome(int x) {string s = to_string(x);int left = 0, right = s.size() - 1;while (left < right) {if (s[left] != s[right]) {return false;}left++;right--;}return true;}
};
class Solution {
public:bool isPalindrome(int x) {string s = to_string(x); // 转字符串int left = 0, right = s.size() - 1; // 左右指针while (left < right) { // 向中间靠拢if (s[left] != s[right]) { // 发现不一样return false; // 直接开溜}left++; // 左指针右移right--; // 右指针左移}return true;}
};
class Solution {
public:bool isPalindrome(int x) {int left=0,right=s.size()-1;while(left<right){if(s[left]!=s[right]){ return false; }left++;right--;}return true;}
};
class Solution {
public:bool isPalindrome(int x) {string s=to_string(x); // 转字符串int left=0,right=s.size()-1; // 左右指针while(left<right){ // 向中间靠拢if(s[left]!=s[right]){ // 发现不一样return false; // 直接开溜}left++; // 左指针右移right--; // 右指针左移}return true;}
};
解题思路(数学版)
解法三:数学反转
解题思路:题目要求处理整数,那我们应该用数学方法才够"纯正"。反转数字可以通过数学运算实现,这样才配得上这道题的"整数"标签!
分析代码:还是那个int x,但这次我们要用真正的数学方法了!
提出假设:通过取模和除法运算反转数字,然后比较原数字与反转后的数字。
验证假设:
-
121 → 反转得到121 → 相等 ✓
-
123 → 反转得到321 → 不相等 ✓
发现问题:反转后的数字可能溢出!比如2147483647反转后就溢出了,而且完全反转效率也不高。
改进假设:只反转一半数字!这样既避免了溢出,又提高了效率,我真是个天才!
最终方案:反转后半部分,然后比较前半部分和反转后的后半部分。
直接上代——码!
AC Code:
class Solution {
public:bool isPalindrome(int x) {if (x < 0) return false;if (x < 10) return true;if (x % 10 == 0) return false;int reversed = 0;while (x > reversed) {reversed = reversed * 10 + x % 10;x /= 10;}return x == reversed || x == reversed / 10;}
};
class Solution {
public:bool isPalindrome(int x) {if (x < 0) return false; // 负数肯定不是回文if (x < 10) return true; // 个位数肯定是回文if (x % 10 == 0) return false; // 以0结尾的不是回文int reversed = 0; // 存储反转的后半部分while (x > reversed) { // 当原数大于反转数时继续reversed = reversed * 10 + x % 10; // 反转数字x /= 10; // 原数去掉最后一位}// 偶数位:x == reversed// 奇数位:x == reversed/10 (去掉中间那位)return x == reversed || x == reversed / 10;}
};
class Solution {
public:bool isPalindrome(int x) {if(x<0) return false;if(x<10) return true;if(x%10==0) return false;int reversed=0;while(x>reversed){reversed=reversed*10+x%10;x/=10;}return x==reversed||x==reversed/10;}
};
class Solution {
public:bool isPalindrome(int x) {if(x<0) return false; // 负数肯定不是回文if(x<10) return true; // 个位数肯定是回文if(x % 10==0) return false; // 以0结尾的不是回文int reversed=0; // 存储反转的后半部分while(x>reversed){ // 当原数大于反转数时继续reversed=reversed*10+x%10; // 反转数字x/=10; // 原数去掉最后一位}// 偶数位:x==reversed// 奇数位:x==reversed/10 (去掉中间那位)return x==reversed||x==reversed/10;}
};
解法四:完全反转数字法
解题思路:既然要反转,那就彻底一点!把整个数字都反转过来比较,简单直接!
分析代码:还是那个int x,这次我们用long long来避免溢出问题。
提出假设:完全反转整个数字,然后比较反转前后是否相等。
验证假设:
-
121 → 反转121 → 相等 ✓
-
123 → 反转321 → 不相等 ✓
-
-121 → 反转121-?不对,负数直接返回false ✓
得出结论:完全反转法最直观易懂,就是要注意溢出问题,所以用了long long。
血的教训:
直接给我上代——码!
AC Code:
class Solution {
public:bool isPalindrome(int x) {if (x < 0) return false;long long reversed = 0;int temp = x;while (temp != 0) {reversed = reversed * 10 + temp % 10;temp /= 10;}return x == reversed;}
};
class Solution {
public:bool isPalindrome(int x) {if (x < 0) return false; // 负数不是回文long long reversed = 0; // 用long long防止溢出int temp = x; // 保存原始值while (temp != 0) { // 反转整个数字reversed = reversed * 10 + temp % 10;temp /= 10;}return x == reversed; // 比较是否相等}
};
class Solution {
public:bool isPalindrome(int x) {if(x<0) return false;long long reversed=0;int temp=x;while(temp!=0){reversed=reversed*10+temp%10;temp/=10;}return x==reversed;}
};
class Solution {
public:bool isPalindrome(int x) {if(x<0) return false; // 负数不是回文long long reversed=0; // 用long long防止溢出int temp=x; // 保存原始值while(temp!=0){ // 反转整个数字reversed=reversed*10+temp%10;temp/=10;}return x==reversed; // 比较是否相等}
};
总结
四种解法各有特色:
-
字符串反转法:简单粗暴,适合新手
-
双指针法:聪明伶俐,提前退出
-
1数学反转法:优雅高效,真正的大佬解法
-
完全反转法:直观易懂,就是要注意溢出
个人最推荐解法三和解法一,非常符合题目要求!(指的是可不可以不用字符串捏?以及 不用字符串怎么解捏?)
重中之重!!!
在文章的最后,提前祝各位神犇小伙伴们1024快乐!对了,点赞收藏关注一个再走呗?