如何优雅地反转有符号整数
题目描述
整数反转
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
示例 3:
输入:x = 120
输出:21
示例 4:
输入:x = 0
输出:0
题目分析
这题之所以是简单题,是因为确实有简单解法,大部分都知道。
常规解法
此题看起来非常简单,就是一个字符串反转问题。一串数字在js中可以转化为字符串,然后调用反转api就可以了,就像这样:
var s = 123;
s= s.toString() // '123'
s= s.split('').reverse().join('') // '321'
s= parseInt(s) // 321
这种写法问题不大,不过此题还要包括有符号整数,即负数的情况,这种情况下,得先求绝对值,完了后再变成负的。因为一个负整数经过.toString()后,负号也变字符串了,所以负整数就得这样处理:
var s= -123;
s = Math.abs(s);
s= s.toString() // '123'
s= s.split('').reverse().join('') // '321'
s= parseInt(s) // 321
s= -s
最后总结下来就是这样写:
var reverse = function(x) {
var res = 0;f=false;
if(x<0){
x=Math.abs(x);
f = true
}
res= x.toString()
res= res.split('').reverse().join('')
res= parseInt(res)
if(f)res = -res;
if (res < Math.pow(-2, 31) || res > Math.pow(2, 31) - 1) {
return 0;
}
return res;
};
需要注意是题目中提到此有符号整数是有范围的,所以在后面要加上相关判断。
高级解法
下面来介绍一种高级解法,所谓的高级解法也不过是用到了一点数学知识而已。这个解法的关键思路就是每次循环时把原始数字的末位数取出来并保存,然后在下一次遍历时将保存的值乘以10,再加上当前取出的末位数。这样循环下去,直到原始数字被拆解完。
用代码表达起来就是这样:
let rev = 0;
while (x !== 0) {
const rmder = x % 10; //取最末位数字(带符号)
x = ~~(x / 10); //两次按位取反,可以去除小数部分
rev = rev * 10 + rmder;
if (rev < Math.pow(-2, 31) || rev > Math.pow(2, 31) - 1) {
return 0;
}
}
return rev;
关键的就是这两行代码 "const rmder = x % 10; x = ~ ~(x / 10);"第一句就是为了取出末位数字,第二句就是为了得到原始数字在失去了末位数字之后的值。
最终的结果rev = rev * 10 + rmder;也比较好理解,每取出一个余数,反转过来就要在下次循环时逐次乘以10倒推晋升到高分位。比如,原来是123,第一次遍历后得到3,再遍历就是32,最后就是321了,3逐渐从个位增长到十分位最后再百分位;
整个过程对有符号整数即负数也是适用的。
最后的最后就是要注意下数值范围就可以了。
复杂度分析
就说下高级解法的
时间复杂度就是O(log|x|),即原始十进制数字的位数
空间复杂度是O(1),常量阶的变量
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-integer
参考:
https://leetcode-cn.com/problems/reverse-integer/solution/zheng-shu-fan-zhuan-by-leetcode-solution-bccn/
扫码关注 字节逆旅 公众号,为您奉献更多技术干货!