题目描述
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例:
输入:x = 123
输出:321
输入:x = -123
输出:-321
输入:x = 120
输出:21
输入:x = 0
输出:0
输入:x = 1534236469
输出:0
提示:
- -231 <= x <= 231 - 1
- 负数负号不反转
- 反转后第一位不为0
解答
一开始就想到了转换为字符串暴力求解
我没有一颗算法的心,作为一个算法小白总是习惯性的暴力求解,主要是复杂的实在是一开始想不出来。还好暴力求解也做出来了(第一次交的还挂了。。),先看看我暴力求解的代码(真的啰嗦-_-~)
暴力求解
知识点:
toString()
:可把一个 Number 对象转换为一个字符串,并返回结果。返回的字符长度为1。- 语法:
NumberObject.toString(radix)
- 语法:
charAt()
:可返回指定位置的字符- 语法:
stringObject.charAt(index)
- 语法:
substring()
:用于提取字符串中介于两个指定下标之间的字符- 语法:
stringObject.substring(start,stop)
,第二个参数stop
可选 - 说明:
substring()
方法返回的子串包括start
处的字符,但不包括stop
处的字符。
- 语法:
split()
:用于把一个字符串分割成字符串数组- 语法:
stringObject.split(separator,howmany)
,第二个参数可选 - 说明:
- 返回的数组中的字串不包括 separator 自身
- 如果把空字符串 ("") 用作 separator,那么
stringObject
中的每个字符之间都会被分割
- 语法:
reverse()
:用于颠倒数组中元素的顺序- 语法:
arrayObject.reverse()
- 说明:该方法会改变原来的数组,而不会创建新的数组。
- 语法:
join()
:用于把数组中的所有元素放入一个字符串- 语法:
arrayObject.join(separator)
,参数可选 - 说明:元素是通过指定的分隔符进行分隔的
- 语法:
var reverse = function(x) {
// 将x转换为字符串
var str = x.toString();
// 判断str在长度不为1的情况下最后一位是否为0
// 为0的话,反转后第一位会是0
if (str.charAt(str.length-1) == '0' && str.length > 1) {
// 为0的话就舍弃
str = str.substring(0, str.length - 1);
}
// 去除负数的负号
str = x < 0 ? ("-" + str.substring(1).split("").reverse().join("")) : str.split("").reverse().join("");
// 对反转后的数进行溢出判断
if(str > Math.pow(2, 31) - 1 || str < Math.pow(-2, 31)) return 0;
return str;
}
其中遇到的问题:
上面提到过我第一次提交的时候挂了,是因为我是对没有反转后的x进行溢出判断
,而是判断了反转前的,但是反转后的数会有溢出的可能
非暴力求解法
这个是Leecode上一位大佬写的,跟我的比起来高级了不知道多少倍,真的巧妙。他的办法是,通过取余,位非运算符(~)来一个一个数取反
-
~
运算符(位非)用于对一个二进制操作数逐位进行取反操作-
第 1 步:把运算数转换为 32 位的二进制整数。
-
第 2 步:逐位进行取反操作。
-
第 3 步:把二进制反码转换为十进制浮点数。
-
总的来说就是对数字进行取负运算,再减 1
-
那么
~~
,就是进行两次取反-
# 对 -12.2 进行位非运算,则返回值为 -12 ~12 = -12-1 = -11.2 # 那么 ~~12 = -(-13)-1 = -12 # 结论 ~~可以去掉小数
-
跟
Math.floor()
不同的是,它只是单纯的去掉小数部分,不论正负都不会改变整数部分。-12.2
按照Math.floor()
的做法就会等于-13
-
-
var reverse = function(x) {
let res = 0;
while(x){
res = res * 10 + x % 10;
if(res > Math.pow(2, 31) - 1 || res < Math.pow(-2, 31)) return 0;
x = ~~(x / 10);
}
return res;
};
代码说明
:
- 每一次都利用取余来获得整数的最后一位,任何整数不管能不能除尽10,最后得到的余数都是整数本身的最后一位
- 将反转后的数存在res中,在通过
res * 10
,然后res存的数位数提升,在通过~~(x / 10)
除10去掉小数,去掉x的最后一位。例如- 开始x=123,res = 0
- 第一次x=123,res = 0 * 10+123 % 10 = 3,x=~~(123 / 10) = 12
- 第二次x=12,res = 3 * 10+12 % 10 = 30 + 2 = 32,x=~~(12 / 10) = 1
- 第三次x=1,res = 32 * 10+1 % 10 = 320 + 1 = 321,x=~~(1 / 10) = 0