力扣: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); // 转换为string
        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);
        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); // 转换为string
        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;
    }
};

解法二:字符串双指针

解题思路:回文就是首尾对称,那何必整个反转?从两头往中间比较就行了,发现不对劲立马开溜!

分析代码:题目还是给那个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. 字符串反转法:简单粗暴,适合新手

  2. 双指针法:聪明伶俐,提前退出

  3. 数学反转法:优雅高效,真正的大佬解法

  4. 完全反转法:直观易懂,就是要注意溢出

个人最推荐解法三和解法一,非常符合题目要求!(指的是可不可以不用字符串捏?以及 不用字符串怎么解捏?

重中之重!!!

在文章的最后,提前祝各位神犇小伙伴们1024快乐!对了,点赞收藏关注一个再走呗?

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值