给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入: x = 123
输出: 321
示例 2:
输入: x = -123
输出: -321
示例 3:
输入: x = 120
输出: 21
示例 4:
输入: x = 0
输出: 0
提示:
-2^31 <= x <= 2^31 - 1
看到这个题的时候,大家第一时间想到的可能是以下的第一种实现方式:
/**
* @param {number} x
* @return {number}
*/
const reverse = function (x) {
let s = x.toString();
let negative = s.startsWith('-');
s = negative ? s.substring(1, s.length) : s;
s = s.split('').reverse().join('');
let num = negative ? -(parseInt(s)) : parseInt(s);
if (num >= Math.pow(2, 31) - 1 || num <= Math.pow(-2, 31)) {
return 0;
}
return num;
};
这种实现方式虽然好,转字符串非常占用内存,而且还解决不了不能存储64位整数这个问题,假设这个数就是一个64位整数,当执行到parseInt的时候就开始报错了,因此我们想到了另外一个方案,我们每次取一位数然后校验是否超出存储范围,以下是代码实现方式:
/**
* @param {number} x
* @return {number}
*/
const reverse = function (x) {
// 提前计算出数据范围
let max = Math.pow(2, 31) - 1;
let min = Math.pow(-2, 31);
// 初始化反转的数字
let rev = 0;
// 只要x不为0,则循环继续
while (x) {
// 每次将之前反转的数字乘以10,再取出剩余末尾一位数字,将两者相加
rev = rev * 10 + x % 10;
// 这里使用取证,当大于0和小于0的时向下取整的方式不一样,这里很有意思,建议大家试一试
x = x > 0 ? Math.floor(x / 10) : Math.ceil(x / 10);
// 判断是否超出数据范围
if (rev >= max || rev <= min) {
return 0;
}
}
return rev;
};