剑指 Offer 20. 表示数值的字符串 (正则 逐步分解)

文章目录

  • 题目描述
    • 题目分析
    • 法一:
      • 完整代码:
    • 法二:
      • 完整代码:

题目描述

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
若干空格
一个 小数 或者 整数
(可选)一个 ‘e’ 或 ‘E’ ,后面跟着一个 整数
若干空格
小数(按顺序)可以分成以下几个部分:
(可选)一个符号字符(‘+’ 或 ‘-’)
下述格式之一:
至少一位数字,后面跟着一个点 ‘.’
至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
一个点 ‘.’ ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
(可选)一个符号字符(‘+’ 或 ‘-’)
至少一位数字
部分数值列举如下:
[“+100”, “5e2”, “-123”, “3.1416”, “-1E-16”, “0123”]
部分非数值列举如下:
[“12e”, “1a3.14”, “1.2.3”, “±5”, “12e+5.4”]

示例 1:
输入:s = “0”
输出:true

示例 2:
输入:s = “e”
输出:false

题目分析

这道题其实刚上来的第一思路就是把所有的情况全部分析出来,然后分别处理。
不过这样做并不是很好,除非你能N刷这道题,不然考试或者面试的时候很容易漏情况导致调试半天心态崩掉。
包括用状态机做这个题,状态机做这个题要分出来八九种情况,还要找状态转移关系,也是很多很杂。

所以这道题最好用的方法就是异常判断,面试考试最好用的方法就是正则。

法一:

先来一个简单的方法, 其实题目要求就是判断科学计数法是否符合规范,使用python的float转换,如果能转换成功则是合规的。
所以直接用tyr异常判断就行了。

完整代码:

class Solution:
    def isNumber(self, s: str) -> bool:
        try:
            float(s)
        except:
            return False
        return True

法二:

面试考试遇到这道题,就直接正则吧。

先分析一下整体合规的式子:可有可无的正负号 + 小数或整数 + 可有可无的e + 可有可无的正负号 + 整数

先放代码 然后分析。

re.match(r'^[+-]?(\d+\.?\d*|\.\d+)([Ee][+-]?\d+)?$'
  • 开头的^和结尾的$ 表示从开头匹配到结尾,要完整匹配整个输入字符串。
  • [+-]? :表示匹配+或者-符号 ,0次或者1次。 表示匹配前面的字符0次或1次。
  • (\d+\.?\d*|\.\d+): 这一串表示匹配小数或者整数,| 字符表示或,将这一串分割成了两个部分.
    • 第一部分\d+\.?\d*\d+ 匹配1个或者多个数字,+表示匹配前方字符一次或多次。\.? 表示匹配 . 0次或1次,\d* 表示匹配数字0次或多次。 整个第一部分中有一个\.? ,表示小数点可有可无,也就是这一部分可以为小数,可以为整数。若为小数,则其前必有数字,后可有可无。
    • 第二部分\.\d+,就是匹配了 小数点前无数,后面有数的情况。

- ([Ee][+-]?\d+)? :这一串主要是控制e以及后面的字符, 首先这一段是可有可无的,因为e本身就可有可无嘛,所以最后有一个?表示前一段出现0次或1次。[Ee]表示选择大写E或者小写e。e后面必有数字嘛,要么是正负号,要么就是数字。所以再加上,[+-]? 表示匹配+或者-符号 ,0次或者1次。\d+匹配数字一次或多次。

完整代码:

class Solution:
    def isNumber(self, s: str) -> bool:
        import re
        return bool(re.match(r'^[+-]?(\d+\.?\d*|\.\d+)([Ee][+-]?\d+)?$',s.strip()))

你可能感兴趣的:(leetcode,python,算法)