Leetcode #9 回文数

 

Leetcode #9 回文数(Easy, math)

判断给定的整数是否为回文数,并返回一个布尔值。

 

Method 1: 转str的无脑解法(Python 3, 88ms 81%, 14MB 5%):

由于之前题目(#7)的惯性,我将给出的x转变为string,然后判断对称的两位数是否一致。(需要考虑x的位数)

 1 class Solution:
 2     def isPalindrome(self, x: int) -> bool:
 3         if x < 0:
 4             return False #由于负号的存在,负数绝不回文(示例2)
 5         elif x < 10:
 6             return True #个位数、0的情形
 7         elif x % 10 == 0:
 8             return False #能被10整除的数不回文(示例3)
 9         
10         string = str(x)
11         total_length = len(string)
12         if total_length % 2 == 0:
13             for i in range(total_length // 2):
14                 if string[i] != string[total_length - 1 - i]:
15                     return False
16         else:
17             for i in range(total_length // 2 + 1):
18                 if string[i] != string[total_length - 1 - i]:
19                     return False
20         return True

条件判断语句是一些取巧的方式,比如一定不会出现回文的情况——负数、被十整除,或者一定回文的情况——从0到9的一位整数。除了这些易于判断的情况之外,其他的x将被转换为字符串,并且判断对称的两位数(第1位数和个位数、第2位数和十位数......)是否一致。此时我认为有必要判断数字共有多少位数,如为偶位数则依次判断即可,奇位数则忽略在最中间的那一位数。最终的运行情况是:时间复杂度88%,空间复杂度5%。

 Method 1a:不用字符串的无脑解法(Python 3)

由于题目的进阶设定要求在不将x转为字符串的情况下解决问题,所以这里需要采用数学解法来比较对称位置的两位数是否相等。

 1 class Solution:
 2     def isPalindrome(self, x: int) -> bool:
 3         if (x < 0) :
 4             return False
 5         elif x < 10:
 6             return True
 7         elif x % 10 == 0:
 8             return False
 9         
10         temp = x 
11         tool = 1 #tool用来表示x的位数,如x为五位数,则tool = 10000.
12         while (temp >= 10):
13             tool *= 10
14             temp = temp // 10
15             
16         while (x != 0):
17             if (x//tool) != x % 10 : #x目前的最高位和最低位进行比较,如不相等则为False
18                 return False
19             x = (x % tool) // 10 
20             tool = tool / 100 
21             #运算完成后,x的最高位和最低位被除去(如line 19)所示,那么x对应的tool值应当减少两位(除以100)
22         return True

与Method 1相比,1a并没有解决思路上的本质转变,仍然是对对称数位的比较,故其时空复杂度没有明显改善。

 

Method 2: 取巧——翻转一半(Python 3)

class Solution:
    def isPalindrome(self, x: int) -> bool:
        if (x < 0) or (x % 10 == 0 and x != 0):
            return False
        latter_half = 0
        while (x > latter_half):
            latter_half = latter_half * 10 + x % 10
            x = x // 10
        return (x == latter_half) or (x == latter_half // 10)

伊始的if语句仍然是负数、整十数这两种特例。在判断特例之后,程序将数的后一半进行翻转,即(以abc......xyz为例,每个字母代表数字的一位数):

初始:0 → 第一次循环:z → 第二次循环: z*10 + y → 第三次循环: (z*10 + y) * 10 + x → .......

配合这一过程,x的最后一位也会被依次剔除出去(方法是x // 10,除以10并取整)

 

1.如果x的位数为奇,那么当且仅当后半部分(latter_half)比x的剩余部分多一位时,while循环结束。这时我们剔除掉latter_half中的个位数(这位数原本位于x的正中间),判断latter_half剩余部分与x的剩余部分是否相等,如是则为回文数。

2. 如果x位数为偶,那么while停止存在两种可能。(1)x与latter_half位数相同,但x ≤ latter_half,此时应判断x与latter_half的大小,如相等则为回文数;(2)x与latter_half位数不同,那么此时latter_half必然比x多两位,而且说明x与latter_half位数相同时,while并没有跳出,即x > latter_half的情况被满足,这种情况自然是不回文的。

posted @ 2019-09-03 13:21  Alexa_Liu  阅读(128)  评论(0)    收藏  举报