前言
网上有很多LeetCode的刷题指南可以值得借鉴,我本人是按照难度来刷的,目前全部都是难度为简单的题目,等后面刷到中等难度后,会在题目里标注出来。
题目描述
原题见链接:整数反转,以下是题目截屏内容:
题目理解
我一拿到这道题目,第一反应就是,需要通过除以10取余数来把所有位置上的数字依次拿出来,拿出个位数的数字后,原数就减去个位数再除以10,比如123,除以10余3,就减去3,得到120,再除以10,就得到12;然后依次类推,直到拿到所有的数字。
这种反转的样式和栈的存储模式很像,先入后出,所以我当时想的是利用栈结构来做,可是Python是没有栈的数据结构的,所以所幸那就拿个列表通过.extend()功能来一个一个存储下来吧。最后,再按照反转后的顺序,哪一个位置的数需要乘以 10 的多少次方,再都加起来。接着再进行一些判断,就可以输出值了。
我的代码
按照我的理解,我的代码就是这样:
class Solution:
def reverse(self, x: int) -> int:
s = []
l,y = 1,0
if x == 0:
return 0
else:
if x < 0 :
l = -1
x = -x
while(x!=0):
s.extend([x%10])
x = (x - x%10)/10
n = len(s)
for i in range(n):
y += s[i] * 10**(n-1-i)
if y > 2**31 -1 or -y < - 2**31:
return 0
else:
return int(y*l)
虽然通过了,但是用时仅超过了27%的用户,内存消耗仅超过了34%的用户,所以有待提高。
官方代码
这里直接给出官方代码,其链接为:官方代码—整数反转,具体内容见下:
class Solution:
def reverse(self, x: int) -> int:
INT_MIN, INT_MAX = -2**31, 2**31 - 1
rev = 0
while x != 0:
# INT_MIN 也是一个负数,不能写成 rev < INT_MIN // 10
if rev < INT_MIN // 10 + 1 or rev > INT_MAX // 10:
return 0
digit = x % 10
# Python3 的取模运算在 x 为负数时也会返回 [0, 9) 以内的结果,因此这里需要进行特殊判断
if x < 0 and digit > 0:
digit -= 10
# 同理,Python3 的整数除法在 x 为负数时会向下(更小的负数)取整,因此不能写成 x //= 10
x = (x - digit) // 10
rev = rev * 10 + digit
return rev
对比一下官方的思路,和我的思路,最大的不同点在于,官方代码只用了一个循环体!!!。对比之下,发现我的方法是把所有的数都取出来了,然后再计算反转后的数字,但是官方代码,是边取数字边计算反转后的数字(具体就是倒数第二行和倒数第三行),这样的速度肯定更快!在内存方面,仅利用几个变量反复替换,也节省了空间消耗。
总结
这个题做完我有以下感悟:
- 慎用循环体
循环虽然好用,但是很自然地也增加了计算复杂度;所以能不用循环,就不用循环,能少用一个,就少用一个。但话又说回来,能不能少用一个循环体是算法决定的,你想到的算法就是这样,那也没办法。 - 多想想还有没有更好的方案
这让我想起来上小学还是初中的时候,语文老师教写作文,说,当你拿到一个题目想到的第一个思路,一定不要写,你能想得到,那别人也能想的到,你要再想第二个或者第三个,往往更新颖,或是更有深度等等。我想,写算法可能也是一样的道理。 - 尽可能挖掘更多深层次的特征
这道题之所以可以只用一个循环体就搞定,最大的特点就在于,计算反转后的数字的过程,它和每次取余数的过程是高度相关的,是对易的。正是基于这一点,所以他们可以放在一个循环体内进行,大大减少了计算量。
比如,x=123这个数,digit=x%10=3,取出来了;更新x,所以x=12;接着计算rev,rev=rev * 10 + digit = 3;
下一次循环,x = 12, digit = x % 10 = 2;更新x,所以x = 1;接着计算rev,rev = rev *10 + digit = 32;
发现了没有,x 每次踢掉最后的个位数要除以10,而反转后的数字每次要乘以10,正是这样的对易关系,使得他们可以放在一个循环体内。
《教父》里这么说,“一个人如果不能在第一时间就看穿事物的本质,就注定要比别人走更多的弯路”。所以,如何在第一时间就看穿一道题,一个计算过程,以及一种算法的本质,才是最重要的。而这种能力,不仅需要不断地学习、积累更多的算法知识和套路,而且需要长期的、有意识的、刻意的训练!
加油!!!