• LeetCode 第9题:回文数(Python3解法)


    1:问题描述

    来源:LeetCode

    难度:简单


    问题详情:
    给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false

    回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

    • 例如,121 是回文,而 123 不是

    输入:x = 121
    输出:true

    输入:x = -121
    输出:false
    解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

    输入:x = 10
    输出:false
    解释:从右向左读, 为 01 。因此它不是一个回文数

    进阶:你能不将整数转为字符串来解决这个问题吗?


    2:问题分析

    从给出的示例可以看出:

    • 负数不是回文数
    • 位数大于1且末尾为0的数不是回文数

    同时,也可以想到:

    • 只有1位的数是回文的

    2.1 时间复杂度和空间复杂度

    在真正开始介绍各种算法前,先以表格形式展示各自的时间复杂度和空间复杂度。

    算法时间复杂度空间复杂度
    字符串法 O ( l o g ( x ) ) O(log(x)) O(log(x)) O ( l o g ( x ) ) O(log(x)) O(log(x))
    直接法O( l o g ( x ) log(x) log(x)) O ( 1 ) O(1) O(1)
    折半法O( l o g ( x ) log(x) log(x)) O ( 1 ) O(1) O(1)

    2.2 字符串法

    2.2.1 代码

    根据进阶要求的限制,我们反而能够很容易想到这个解法。将数字转换为字符串列表,然后反转列表,再转换为数字对比是否与反转前相等即可。
    同时将分析得到的三种情况先做一个返回。

    def isPalindrome(x: int) -> bool:
        """不满足进阶要求"""
        if x < 0:
            return False
        if 0 <= x <= 9:
            return True
        if x % 10 == 0:
            return False
        rev_x = int(''.join(list(str(x))[::-1]))
        if rev_x == x:
            return True
        else:
            return False
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    由于数字长度可以用 i n t ( l o g 10 ( x ) ) + 1 int(log10(x))+1 int(log10(x))+1计算得到,因此时间复杂度为 O ( l o g ( x ) ) O(log(x)) O(log(x))
    对于空间复杂度,由于其需要一个列表存储每一位数值,因此空间复杂度为 O ( l o g ( x ) ) O(log(x)) O(log(x))

    2.3 直接法

    2.3.1 代码

    不使用字符串的前提下,我们就需要真的将数值反转过来对比。

    def isPalindrome2(x: int) -> bool:
        """数值计算转换"""
        if x < 0:
            return False
        if 0 <= x <= 9:
            return True
        if x % 10 == 0:
            return False
        rev_x = 0
        s = x
        while s:
            s, t = divmod(s, 10)
            rev_x = rev_x * 10 + t
        if rev_x == x:
            return True
        else:
            return False
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    由于数字长度可以用 i n t ( l o g 10 ( x ) ) + 1 int(log10(x))+1 int(log10(x))+1计算得到,因此时间复杂度为 O ( l o g ( x ) ) O(log(x)) O(log(x))
    对于空间复杂度,其为 O ( 1 ) O(1) O(1)

    2.3 折半法

    2.3.1 代码

    折半法其实是直接法的优化,因为其实我们并不需要将所有的位数都反转,而只需反转一半,然后对比是否与另一半未反转的相同即可。

    举例来说,1221,我们只需反转后半部分的2112,然后对比前半部分看是否一致。

    def isPalindrome4(x: int) -> bool:
        if x < 0:
            return False
        if 0 <= x <= 9:
            return True
        if x % 10 == 0:
            return False
    
        rev_x = 0
        while x > rev_x:
            x, t = divmod(x, 10)
            rev_x = rev_x * 10 + t
    
        return rev_x == x or rev_x // 10 == x
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    虽然思想上比较简单,但是,我们如何判断当前已经完成了一半的反转了呢?

    对此,我们可以反过来想,当还未完成反转的时候有什么特点?

    • 那就是前半部分的位数比后半部分的位数多,可以使用前半部分>反转的后半部分作为循环判断的依据。
    • 但是在位数相同的情况下,也可以达到前半部分>后半部分这种情况。比如3221这个数,其在反转的过程中够实现这个特例,32>12
      对此,我们只能让后半部分暂时占点便宜,让其再次循环多取走一位,变成3 < 122这样就可以终止循环。
      然后我们就前部分==后部分 或者 前部分==后部分//10 作为返回值。可以判断前半部分3和后半部分122这两个判断条件都不满足,就是false了。

    前部分==后部分//10 这个条件是为了应对输入的数x位数是奇数的情况,比如121。
    按照while的流程:

    前半部分后半部分
    1210
    121
    112

    我们可以看出,前部分占了1位,后半部分占了2位,我们需要使用前部分==后部分//10 去除多后半部分出来的末位2,去除后左右两边都为1,返回true.

    由于数字长度可以用 i n t ( l o g 10 ( x ) ) + 1 int(log10(x))+1 int(log10(x))+1计算得到,因此时间复杂度为 O ( l o g ( x ) ) O(log(x)) O(log(x))
    对于空间复杂度,其为 O ( 1 ) O(1) O(1)

  • 相关阅读:
    【Redis专题】RedisCluster集群运维与核心原理剖析
    APS的主要功能有哪些?你了解吗?
    .net餐厅管理系统数据层餐厅服务类修改、查询菜品信息
    怎么把音频转换成mp3,一键批量转换法
    Excel - 使用VBA通过ADO数据库连接来操作一个Excel数据源
    怎么使用动态代理IP提升网络安全,动态代理IP有哪些好处呢
    Linux fcntl函数
    算法基础(一)| 快速排序和归并排序详解
    【shell】read -t -n1
    基于KubeEdge的边缘节点分组管理设计与实现
  • 原文地址:https://blog.csdn.net/weixin_43490422/article/details/126681762