Python刷LeetCode之题目#7整数反转

本文分享了一种使用Python解决LeetCode整数反转问题的方法,通过分析题目并避免使用额外的数据结构,实现了仅用一个循环体的高效解决方案。作者反思了算法设计,强调慎用循环体,思考更好的方案,并深入挖掘问题本质的重要性。
摘要由CSDN通过智能技术生成

Python刷LeetCode之题目#7整数反转


前言

网上有很多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

对比一下官方的思路,和我的思路,最大的不同点在于,官方代码只用了一个循环体!!!。对比之下,发现我的方法是把所有的数都取出来了,然后再计算反转后的数字,但是官方代码,是边取数字边计算反转后的数字(具体就是倒数第二行和倒数第三行),这样的速度肯定更快!在内存方面,仅利用几个变量反复替换,也节省了空间消耗。


总结

这个题做完我有以下感悟:

  1. 慎用循环体
    循环虽然好用,但是很自然地也增加了计算复杂度;所以能不用循环,就不用循环,能少用一个,就少用一个。但话又说回来,能不能少用一个循环体是算法决定的,你想到的算法就是这样,那也没办法。
  2. 多想想还有没有更好的方案
    这让我想起来上小学还是初中的时候,语文老师教写作文,说,当你拿到一个题目想到的第一个思路,一定不要写,你能想得到,那别人也能想的到,你要再想第二个或者第三个,往往更新颖,或是更有深度等等。我想,写算法可能也是一样的道理。
  3. 尽可能挖掘更多深层次的特征
    这道题之所以可以只用一个循环体就搞定,最大的特点就在于,计算反转后的数字的过程,它和每次取余数的过程是高度相关的,是对易的。正是基于这一点,所以他们可以放在一个循环体内进行,大大减少了计算量。
    比如,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,正是这样的对易关系,使得他们可以放在一个循环体内。

《教父》里这么说,“一个人如果不能在第一时间就看穿事物的本质,就注定要比别人走更多的弯路”。所以,如何在第一时间就看穿一道题,一个计算过程,以及一种算法的本质,才是最重要的。而这种能力,不仅需要不断地学习、积累更多的算法知识和套路,而且需要长期的、有意识的、刻意的训练!

加油!!!

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值