栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【算法】7. 整数反转

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【算法】7. 整数反转

这是来自力扣的第7道算法题,题目是:

这道题是一道简单题,但是我不会做,绞尽脑汁没有想出来(我承认自己菜鸡)。

先来看一下题目,是一个32位的有符号整数,在计算机中,8位是一个字节,32位就是4字节。而在Java中,4字节的整数就是int类型,而题目要求不允许存储64位的整数,那么意思就是这道题中不让使用long类型。

继续看题,如果反转后超过int类型的范围,就返回0。这里思考一下为什么会超出这个范围呢?比如说给出的整数为-2的31次方,它反转后的结果就是2的31次方,而int最大的范围是2的31次方-1,会超出取值范围,所以如果最终得到的结果是2的31次方,直接返回0。

然后看示例,示例1很正常没啥可说的。而示例2,给出的数字是-123,而需要输出的数字是-321,这就说明翻转的时候要保留符号。示例3给出的是120,结果是21,这代表着反转后需要把0给去掉。

看到这里,我的脑海里首先想的是被这个数字变成字符串,判断索引值为0的字符(也就是第一位)是否为负号,如果是的话保留这个符号。然后再把末尾的0删掉,最后进行数组翻转,再转换为数字。可是这样操作的成本好像有点高,代码量也多,不想用也不想写(该题评论区有此解法,可以去看下)。

有没有简单写法?有。

首先,我们可以先定义一个boolean类型的变量,用来判断该数是正数还是负数。如果是负数,该变量的值为true,正数则是false,然后取该数的相反数。

class Solution {
public int reverse(int x) {
        // 定义一个用于判断x是正数还是负数的变量
        boolean flag = false;
        // 如果x为正数,则flag值不变,如果为负数,则取x的相反数,并将flag设置为true
        if(x < 0) {
            x = -x;
            flag = true;
        }
        
    }
}

不过这里插一下,如果x是int类型的最小值,那么他的相反数则是等于int类型的最大值加1,int类型的最大值加1等于int类型的最小值,所以....x还是等于它本身。下图是使用debug测试的结果。

既然要把反转的数字返回,x还需要用,则需要再定义一个变量,用于接收最终的结果。

int res = 0;

重头戏来了,如何反转??!!

如果x等于0,直接返回即可,没必要进行反转。如果等于0的话,再进行反转。

反转可以进行取模运算。

x % 10 得到的结果就是x的个位数,把这个结果赋值给res,这样就反转了第一位数。

取到第一位数之后,第一位数就没用了,可以将x除以10。因为x是int类型的,除以10之后得到的个位数就是之前的十位数,之前的个位数就被丢掉了(好惨)。

此时可以得到代码:

res = x % 10;
x /= 10;

此时的第二位数就是现在x的个位数,再将 x % 10 就能得到,而现在的res的值是刚刚的个位数,将 res * 10 再加上现在得到的第二位数,就是反转后的数。

这里可以得到代码:

res = res * 10 + x % 10;
x /= 10;

其它位数以此类推。

找到规律,上循环:

while(x != 0){
    // 每循环一次 res的值*10,再加上x%10后的值
    // 比如 123 取模后的值是3 第一次循环0*10+3=3  第二次循环3*10+2 
    // 第三次循环 32*10+1  此时结果就是321了
    res = res * 10 + x % 10;
    x /= 10;
}

还记得刚刚的flag吗,如果初始的x是正数,直接返回,如果是负数,取反后返回。

return flag ? -res : res;

别急,还没有结束,如果x的初始值是int类型的最小数,怎么办?这样写得到的结果肯定是不对的,所以要做处理。

打开JDK API的Integer类,在java.lang包中,可以看到有一个常量MAX_VALUE,这个常量表示了int类型的最大值。

刚刚讲了,当 x % 10 的时候可以得到x的个位数。x是经过我们取反的,如果是int的最小值,x % 10 的结果还是个负数,Integer.MAX_VALUE减去这个个位数,减去这个负数,就相当于加上了这个数的相反数,当int类型越界了之后就还是负数。

由此可以得到代码:

if(0 > (Integer.MAX_VALUE - x % 10)) {
    return 0;
}

问题没有那么简单,如果取反操作(x = -x)后和int类型的最大值位数一样,但是x的最高位大于int类型的最大值的最低位,那么反转后也会溢出。解决方法就是将我们刚刚的判断写到循环中,并且再加上点东西:

if(res > (Integer.MAX_VALUE - x % 10) / 10) {
    return 0;
}

最终代码为:

class Solution {
    public int reverse(int x) {
        boolean flag = false;
        if(x < 0) {
            x = -x;
            flag = true;
        }
        int res = 0;
        while(x != 0){
            if(res > (Integer.MAX_VALUE - x % 10) / 10) {
                return 0;
            }
            res = res * 10 + x % 10;
            x /= 10;
        }
        return flag ? -res : res;
    }
}

此时举例说明:

假设x最开始的值是1534236469 

第一次循环:res是0,(Integer.MAX_VALUE - x % 10) / 10 的值是214748363

以此类推,关注最后一次循环

最后一次循环开始之前 x 的值为 1, res 的值为964632435

x % 10 = 1 % 10 = 1

Integer.MAX_VALUE - 1 = 2147483646

2147483646 / 10 = 214748364

如果此时 res 是大于这个值的话,那说明该数字反转后是会溢出的,因为res还需要再进行一次*10的操作,不管加不加最后的只有一位数的x的值都是溢出的

所以直接返回0

怎么样?你看懂了吗?

在力扣上提交代码后得到如下结果

该题虽然是简单题,但我觉得好难。没有做出来的小伙伴也不要气馁(我也没做出来),大家多做多练多看看题解,才能提高自己。

题目来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/reverse-integer/

题目著作权归领扣网络所有

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/606745.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号