整数反转leetcode java_leetcode 7. 整数反转(Java版)

题目描述(题目难度,简单)

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1:

输入: 123

输出: 321

示例 2:

输入: -123

输出: -321

示例 3:

输入: 120

输出: 21

注意:

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为

math?formula=%5B%E2%88%922%5E%7B31%7D%2C%202%5E%7B31%7D%20%E2%88%92%201%5D。请根据这个假设,如果反转后整数溢出那么就返回 0。

示例代码

class Solution {

public int reverse(int x) {

long y = x;

long res = 0;

do{

res = 10*res + y % 10;

}while((y /= 10) != 0);

if(res < Integer.MIN_VALUE || res > Integer.MAX_VALUE){

return 0;

}

return (int)res;

}

}

思路解析

这个题的题目难度虽然被划为简单,但是这一题提交的正确率却是前 7 题里最低的。

7040957f3f9f

image.png

所以我们不能小看它,这个题我原来在一次机试考试中也遇到过,也顺利的解决了。所以最开始我也看轻了这道题,提交好几次都没通过。问题就出在这个题加了可能溢出这个条件,开始我还想有没有比较巧妙的办法,提前判断反转后会不会溢出,想了几个方法,但提交发现都有漏洞。最后突然想到,这个溢出这么难判断的原因就是使用 int 去存反转后的结果,如果溢出就会把溢出部分的数据位丢掉,导致结果不正确。那我们用一个更长的数据类型(long)去存反转后的结果不就行了,这样肯定不会存在有丢掉数据位的情况。最后直接把反转后的结果与 int 类型的上下限比较即可判断是否溢出。

感觉这是最简洁的办法了,也好记。以后面试遇到就这样回答了(^0^)。

帮大家回忆一下 Java 基本数据类型的长度:

类型

长度(字节)

byte

1

short

2

int

4

long

8

float

4

double

8

char

2

还有一点需要注意的就是,Java 数值类型中没有无符号类型

下面也贴出 leetcode 官方给的题解吧,应该算是标准的正解,但饶了点弯,不如上面的代码简洁好记,给大家对比一下,同时给大家多一个思路。

leetcode 官方题解(内容原样复制)

方法:弹出和推入数字 & 溢出前进行检查

思路

我们可以一次构建反转整数的一位数字。在这样做的时候,我们可以预先检查向原整数附加另一位数字是否会导致溢出。

算法

反转整数的方法可以与反转字符串进行类比。

我们想重复“弹出”

math?formula=x 的最后一位数字,并将它“推入”到

math?formula=%5Ctext%7Brev%7D 的后面。最后,

math?formula=%5Ctext%7Brev%7D 将与

math?formula=x 相反。

要在没有辅助堆栈 / 数组的帮助下 “弹出” 和 “推入” 数字,我们可以使用数学方法。

//pop operation:

pop = x % 10;

x /= 10;

//push operation:

temp = rev * 10 + pop;

rev = temp;

但是,这种方法很危险,因为当

math?formula=%5Ctext%7Btemp%7D%20%3D%20%5Ctext%7Brev%7D%20%5Ccdot%2010%20%2B%20%5Ctext%7Bpop%7D 时会导致溢出。

幸运的是,事先检查这个语句是否会导致溢出很容易。

为了便于解释,我们假设

math?formula=%5Ctext%7Brev%7D 是正数。

如果

math?formula=temp%20%3D%20%5Ctext%7Brev%7D%20%5Ccdot%2010%20%2B%20%5Ctext%7Bpop%7D 导致溢出,那么一定有

math?formula=%5Ctext%7Brev%7D%20%5Cgeq%20%5Cfrac%7BINTMAX%7D%7B10%7D

如果

math?formula=%5Ctext%7Brev%7D%20%3E%20%5Cfrac%7BINTMAX%7D%7B10%7D,那么

math?formula=temp%20%3D%20%5Ctext%7Brev%7D%20%5Ccdot%2010%20%2B%20%5Ctext%7Bpop%7D 一定会溢出。

如果

math?formula=%5Ctext%7Brev%7D%20%3D%3D%20%5Cfrac%7BINTMAX%7D%7B10%7D,那么只要

math?formula=%5Ctext%7Bpop%7D%20%3E%207

math?formula=temp%20%3D%20%5Ctext%7Brev%7D%20%5Ccdot%2010%20%2B%20%5Ctext%7Bpop%7D就会溢出。

math?formula=%5Ctext%7Brev%7D 为负时可以应用类似的逻辑。

class Solution {

public int reverse(int x) {

int rev = 0;

while (x != 0) {

int pop = x % 10;

x /= 10;

if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;

if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;

rev = rev * 10 + pop;

}

return rev;

}

}

怎么样,对比后,是不是发现还是第一种方法更简单更好理解一点呢(嘻嘻)。

补充两点知识点*(也挺重要)

一、取余运算和取模运算的异同

这个题目最开始,我还是分正负数来考虑的,因为我印象里记得 %

对正数和负数的运算好像有区别。最后去查了一下,补充在这里。

C/C++ 和 Java 一样,% 是取余运算;而 Python 的 % 是取模运算。

取余运算和取模运算的区别:

对于整型数

math?formula=a%EF%BC%8Cb 来说,取余运算或者取模运算的方法都是下面两步:

求整数商:

math?formula=c%20%3D%20a%2Fb

计算余数或者模:

math?formula=r%20%3D%20a%20-%20c%5Ccdot%20b

而两者的区别就在于第一步不同:取余运算在取

math?formula=c的值时,向

math?formula=0 方向舍入,而取模运算在计算

math?formula=c的值时,则是向负无穷方向舍入。

例如计算:

math?formula=-7%5C%254

第一步:求整数商,取余运算算出的整数商为

math?formula=c%3D%5Clceil%5Cfrac%7B-7%7D%7B4%7D%5Crceil%3D-1,而取模运算算出的整数商为

math?formula=c%3D%5Clfloor%5Cfrac%7B-7%7D%7B4%7D%5Crfloor%3D-2

第二步:计算余数和模的公式相同,但因

math?formula=c的值不同,取余的结果为

math?formula=-7-(-1%5Ctimes4)%3D-3,取模的结果为

math?formula=-7-(-2%5Ctimes4)%3D1

归纳:当

math?formula=a

math?formula=b符号一致时,取余运算和取模运算的结果一样。

当符号不一致时,结果不一样。取余运算结果的符号和

math?formula=a一致,取模运算结果的符号和

math?formula=b一致。

验证结果如下:

对于 Java 来说,

代码如下:

public class Test {

public static void main(String[] argus){

System.out.println("-7 % 4 = "+(-7%4));

System.out.println("7 % -4 = "+(7%-4));

}

}

运行结果如下:

7040957f3f9f

image.png

对于 Python 来说,

7040957f3f9f

image.png

二、Java 位运算部分知识点

在解这道题的时候,考虑过使用位运算简化代码。虽然最后没用上,但还是记在这吧,万一以后用的上呢。

一、Java 移位运算

<>为右移运算(左边补符号位),>>>为无符号右移运算(左边恒补 0),注意 Java 中没有<<

二、Java 取绝对值的位运算实现

int abs(int x){

return (x+(x = x>>31))^x;//有点过于精炼,哈哈

}

分解一下代码,实际上是有两步,

第一步,令 y = x >> 31

第二步,返回结果 (x+y) ^ y

代码解释如下:

当 x 为正数时,y = 0,则 (x+0) ^ 0 还是 x。

当 x 为负数时,x 右移 31位,左边补符号位 1 ,最终y = 0xFFFFFFFF,也即 y = -1。所以(x+y) ^ y = (x-1)^0xFFFFFFFF = ~(x-1) = -x,perfect!!!

完结撒花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值