[LeetCode]9. 回文数

题目

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例 1:

输入: 121
输出: true

示例 2:

输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:

输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。

进阶:
你能不将整数转为字符串来解决这个问题吗?

解题思路

解法一:转字符数组

将数字先转成字符串,再转换成字符数组。设置 left、right 两个双指针,分别从前往后、从后往前遍历。当遇到不一样的字符时,直接返回 false;如果相同,继续遍历;当遍历完字符数组之后,也没发现不同的字符,则返回true。

复杂度分析:
时间复杂度:O(n)。我们需要遍历整个字符数组。
空间复杂度:O(n)。我们需要O(n)的空间存放字符数组。

解法二:数学解法

将数字本身反转,然后将反转后的数字与原始数字进行比较,如果它们是相同的,那么这个数字就是回文。但是,如果反转后的数字大于 INT.MAX,将遇到整数溢出问题。所以我们考虑只反转 int 数字的一半,如果该数字是回文,其后半部分反转后应该与原始数字的前半部分相同。
例如,输入 1221,我们可以将数字 “1221” 的后半部分从 “21” 反转为 “12”,并将其与前半部分 “12” 进行比较,因为二者相同,所以数字 1221 是回文。
在开始反转之前先处理一些临界情况:1)所有负数都不可能是回文;2)除了 0 以外,所有个位是 0 的数字不可能是回文,因为最高位不等于 0,所以我们可以对所有大于 0 且个位是 0 的数字返回 false。
对于其他正常情况的反转,例如数字 1221,如果执行 1221 % 10,我们将得到最后一位数字 1,要得到倒数第二位数字2,我们可以先通过除以 10 把最后一位数字 1 从 1221 中移除,1221 / 10 = 122,再将结果对 10 取余,122 % 10 = 2,就可以得到倒数第二位数字。然后我们把最后一位数字乘以 10,再加上倒数第二位数字,1 * 10 + 2 = 12,就得到了我们想要的反转后的数字。继续这个过程,将得到更多位数的反转数字。
由于整个过程我们不断将原始数字除以 10,然后给反转后的数字乘上 10,所以,当原始数字小于或等于反转后的数字时,就意味着我们已经处理了一半位数的数字了。
由于回文数的位数可奇可偶,所以当它的长度是偶数时,它对折过来应该是相等的;当它的长度是奇数时,那么它对折过来后,有一个的长度需要去掉一位数(除以 10 并取整)。

具体步骤如下:
1)先判断临界情况。
2)每次进行取余操作 ( %10),取出最低的数字:y = x % 10.
3)将最低的数字加到取出数的末尾:res = res * 10 + y.
4)每取一个最低位数字,x 都要自除以 10.
5)判断 x 是不是小于 res ,当它小于的时候,说明数字已经对半或者过半了。
6)最后,判断奇偶数情况:如果是偶数的话,res 和 x 相等;如果是奇数的话,最中间的数字就在res 的最低位上,将它除以 10 以后应该和 x 相等。

复杂度分析:
时间复杂度:O(logn)。对于每次迭代,我们会将输入除以 10,因此时间复杂度为 O(logn)。
空间复杂度:O(1)。我们只需要常数空间存放若干变量。

代码

解法一:转字符数组

class Solution {
    public boolean isPalindrome(int x) {
        String s = String.valueOf(x);
        char[] nums = s.toCharArray();
        int left = 0;
        int right = nums.length-1;
        while(left<=right){
            if(nums[left]==nums[right]){
                left++;
                right--;
            }else{
                return false;
            }
        }
        return true;
    }
}

解法二:数学解法

class Solution {
    public boolean isPalindrome(int x) {
        // 临界情况
        if(x<0 || (x%10==0 && x!=0)){
            return false;
        }
        int res = 0;
        // 进行反转
        while(x>res){
            res = res*10 + x%10;
            x /= 10;
        }
        // 处理奇偶情况
        return x == res || x == (res / 10);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值