[Leetcode刷题]第七题: 整数反转
本文涉及:数学原理进行出栈操作、python切片反转字符串、取模运算以及求模的原理
最近跑去刷了一下pat,感觉挺适合作为学校课程的同步练习食用。
不管多忙,leetcode还是不过鸽的!(真香?-?)
题目:整数反转
题干:
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
Example1:
1 | 输入: -123 |
Example2:
1 | 输入: 123 |
Example3:
1 | 输入: 120 |
解题思路
第一种解法
我拿到题目后,第一反应是利用堆栈。利用pop
把元素逐个弹出并添加到新的数组中,然后转换类型。
需要注意 的是题目中给定了数值的范围,因此我们需要进行判断。
现在看回来,真是种呆逼的写法啊~ 我就不过多解释了(no eyes to see),照例还是贴个代码吧:
1 | class Solution: |
每次写都知道自己写的是不够完美的,在写的时候我突然记起python有切片操作,不是比这样子更方便吗!
利用切片的优化解法
python的切片功能能快速的操作字符串,这里的原理和上面的大致相同,不过减少了更多的操作。
大致思路就是把int类型转换成string类型,然后用切片将字符串反转。这里需要注意负数的情况!!!然后把字符串转换回去。
代码:
1 | class Solution: |
这是我自己能想到的最优解法了,但结果仍然不太理想。
官方解法
看完官方答案后,我总结了可以优化的点:
- 出栈操作可以通过数学知识来简化
- 并不需要转换类型
- 取值范围的判断
出栈操作思路
算法:
反转整数的方法可以与反转字符串进行类比。
我们想重复“弹出” x 的最后一位数字,并将它“推入”到 res 的后面。最后,res 将与 x 相反。
要在没有辅助堆栈 / 数组的帮助下 “弹出” 和 “推入” 数字,我们可以使用数学方法。
1 | //pop operation: |
用图片来理解:
取值范围判断思路
解决了堆栈的操作后,就剩下取值范围要解决了。
我们知道取值范围是:[−2^31, 2^31 − 1]
. 也就是说它小于2147483647
,大于214748364
假设有1147483649
这个数字,它是小于最大的32位整数的,但是将这个数字反转过来后就变成了9463847411
,这就比最大的32位整数还要大了,这样的数字是没法存到int里面的,所以肯定要返回0(溢出了)。
上图中,绿色的是最大32位整数
第二排数字中,橘子的是5,它是大于上面同位置的4,这就意味着5后跟任何数字,都会比最大32为整数都大。
所以,我们到【最大数的1/10】时,就要开始判断了
如果某个数字大于 214748364那后面就不用再判断了,肯定溢出了。
如果某个数字等于 214748364呢,这对应到上图中第三、第四、第五排的数字,需要要跟最大数的末尾数字比较,如果这个数字比7还大,说明溢出了。
负数同理
这里需要注意!python是向下取整的,也就是说python的取模运算是不准确的。举个栗子:
1 | print(12 % 10) |
可以看到,python的模运算中,负数部分与我们预想的是不一致的。
通过了解,取模与取余是不一样的! 非常amazing啊! 我也是第一次听到,经过了解取模运算的数学表达是这样的:
1 | D = x 对 y 取模 |
因此由于python是向下取整,所以我们要进行正负判断!
代码实现:
1 | class Solution: |
总结
- 找到了知识漏洞:python是向下取整的!
- 明白了取模的数学原理
参考资料
LeetCode: https://leetcode-cn.com/