Python 版 LeetCode 刷题笔记 #7 整数反转

今天迎来了个简单难度的题目,在经历一番中等难度题目的洗礼后,情不自禁露出吊打小朋友的微笑,感觉今天可以多做几道。

我一直说自己的 Python 编码是入门水平,一来是自己摸索着学、并没有接触很深层的专业练习,二来是接触的多是入门级别的问题或练习、对于很多术语及算法都是一头雾水的。这种情况如果我就是业余来学 Python 玩完全够用了,但如果想进一步提升,就不得不经历些辛苦的进阶过程,这也是我打算坚持刷题练习的原因。

话不多说,看题~

题目

中文题目

第 7 题 整数反转:

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例:

输入: 123
输出: 321

输入: -123
输出: -321

输入: 120
输出: 21

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-integer

注意:

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2^31,  2^31 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

英文题目

Question 7 Reverse Integer:

Given a 32-bit signed integer, reverse digits of an integer.

Example:

Input: 123
Output: 321

Input: -123
Output: -321

Input: 120
Output: 21

Note:
Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−2^31,  2^31 − 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

思路

Python 入门阶段,会频繁接触类型转换,将整数转化成字符串来进行翻转,这就是最直接的思路。但要对负数、超出 32 位范围的数做个单独处理。吸取昨天那题的经验,我们尽量对整个处理过程精简化。比如如果负数,我们也用个负数标志来做记录,然后将其转化为正数,这样所有的正负数都可以走同一个处理过程,结束时再对有负数标志的单独返回即可。

代码

class Solution:
    def reverse(self, x: int) -> int:
        # 为负数做个标志
        negative = False
        # 负数情况,标志记录,同时把负数转正方便后续统一处理
        if x<0:
            negative =True
            x = -x
        # 将数字转化为字符串
        s = str(x)
        # 通过字符串的 s[::-1]来进行翻转 “123” 会被转为 “321”
        s_reverse = s[::-1]
        # 将翻转的字符串转化为整数
        x_reverse = int(s_reverse)
        # 负数标志来还原负数
        if negative:
            x_reverse = - x_reverse
        # 根据题目要求,超出范围的返回 0
        if x_reverse < -2**31 or x_reverse>2**31-1:
            return 0
        else:
            return x_reverse        

提交答案

这次运行结果上,用时表现不错,但内存消耗表现挺差:

中文区结果:

执行用时 : 36 ms, 在所有 Python3 提交中击败了 82.58% 的用户
内存消耗 :13.5 MB, 在所有 Python3 提交中击败了 6.67% 的用户

英文版结果:

Runtime: 24 ms, faster than 94.49% of Python3 online submissions for Reverse Integer.
Memory Usage: 14 MB, less than 5.26% of Python3 online submissions for Reverse Integer.

优化

翻看别人的解法,有两个挺有意思。第一个就是和我相同的思路,但是有点酷炫地将代码压缩,有些一行代码的味道:

class Solution:
    def reverse(self, x: int) -> int:
        y=int(str(x)[::-1]) if x>=0 else -int(str(x)[:0:-1])
        return y if -2**31

表现结果:

Runtime: 24 ms, faster than 94.49% of Python3 online submissions for Reverse Integer.
Memory Usage: 13.7 MB, less than 5.26% of Python3 online submissions for Reverse Integer.

处理过程基本一致,少了些中间变量的定义赋值等。这里面有个用法,被称为 Python 的三元表达式:y = true_value if condition else false_value ,即将 if-else 写入一行中,很多一行代码都会用到这个。包括最后这个 return 语句也是这个用法。

第二个值得思考的点也不少,首先刚我们因为整数和字符串间的转换、以及对字符串的翻转处理等导致内存消耗较高。这份代码则完全运用数字计算来完成任务:

class Solution:
    def reverse(self, x: int) -> int:      
        y, res = abs(x), 0
        # 则其数值范围为 [−2^31,  2^31 − 1]
        boundry = (1<<31) -1 if x>0 else 1<<31
        while y != 0:
            res = res*10 +y%10
            if res > boundry :
                return 0
            y //=10
        return res if x >0 else -res

#作者:boywithacoin_cn
#链接:https://leetcode-cn.com/problems/reverse-integer/solution/pythondan-chu-he-tui-ru-shu-zi-yi-chu-qian-jin-xin/

这份代码在作者贴出的表现中表现超好,但我实际提交后效果竟然和用字符串处理的差不多,有点奇怪:

Runtime: 32 ms, faster than 52.34% of Python3 online submissions for Reverse Integer.
Memory Usage: 13.6 MB, less than 5.26% of Python3 online submissions for Reverse Integer.

不纠结表现了,这代码里对 2^31 的处理使用的 1<<31 的方式,采用了 << 位运算符:

a << 2
左移动运算符:运算数的各二进位全部左移若干位,由 << 右边的数字指定了移动的位数,高位丢弃,低位补0。
输出结果 240 ,二进制解释:1111 0000

之后对数字的翻转是靠除以 10 的取余或取整的操作,还是挺有耐心的。

结论

第七题,简单难度,也给了自己多些时间领略别人的代码和思路。感觉今天开始有意识地练习昨天看到的那种对特殊情况做个标记,然后统一来处理。对用位运算符来实现 2 的指数运算也有个了概念,虽然之后可能还是不会去用,但有这么个认知了。再就是 if-else 的三元表达式 true-value if condition else false-value 这个以后可以练起来,刚开始用感觉老会不自觉加上引号。

一周养成一个习惯,哈哈,现在对这种刷题的记录也开始着重记录心得和学到的知识点,不再是单纯代码和注释就完事了,还挺不错的体验。

另外由于这题不难,引发了自己对入门的一些关于入门学习的碎碎念。前几天有朋友转发我一个 Python 入门课程、问值不值得入手买。对于这类课程,作为自学过来的老菜鸟,我是完全不会买的。但这个也要看个人,这种入门课程只能是个开始学习的引子,课程内容不去体验是完全没法评判的。同时,我们所能接触到的大多数 Python 学习推广,无论多么酷炫高大上,大多数的推广者是没有体验过这个课程内容的,更准确地说:多数的推广者并不是通过这类课程学出来的,所以看看就好、结合自己的情况来考虑。如果不想买,那么选些入门级别的书、刷刷题也是很快入门的路子。

至于选什么书、怎么去练习,我觉得要有自己的一个选择标准,结合着你要学来做什么,有针对地筛选和决定,别学了几个月、大半年甚至一两年了还晃荡着沉不下来,那样真的是挺浪费自己的时间。个人感悟,与大家共勉~

你可能感兴趣的:(Python 版 LeetCode 刷题笔记 #7 整数反转)