37.leetCode 65. Valid Number

【题目】:验证输入的字符串能否正确地转换成合法的数字

Validate if a given string is numeric.

Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true

Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.

【分析】:此题需要判断的情况非常多,若直接判断,所耗时间较多;若采用确定有穷状态自动机(DFA)来解决此题,简洁优雅。

【方法1】:参考http://blog.csdn.net/ljiabin/article/details/44980109

思路:把字符串分三段(小数点前、小数点与e/E之间部分、e/E之后),这三段都必须为纯数字组成的字符串。注意,第一部分和第三部分可以带符号(如+12.34e-56),第一部分和第二部分可以有一部分为空(如“.2"或"2.")。

  1. 去掉首尾多余的空格;
  2. 去掉开头的正负号;
  3. 看有没有e或E,如果有那么e/E后面只能是整数;
  4. 再看e前面的部分有没有小数点,小数点前后两部分都必须为整数。

【Python代码】:

    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        s = s.strip()

        if len(s) == 0:
            return False

        if s[0] in ['+', '-']:
            s = s[1:]

        if 'e' in s or 'E' in s: #若包含三部分,则先判断第三部分
            e_pos = s.find('e') if 'e' in s else s.find('E')
            post_e = s[e_pos+1:]
            if len(post_e) == 0:
                return False
            elif post_e[0] in ['+', '-']:
                post_e = post_e[1:]

            if not post_e.isdigit():
                return False
            else:
                s = s[:e_pos]

        if '.' in s: #此时,只包含第一、第二部分,判断第一和第二部分
            substring = s.split('.', 1)
            pre_dot = substring[0]
            try:
                post_dot = substring[1]
            except IndexError: post_dot = ''
            if pre_dot == '' and post_dot == '':
                return False
            elif not pre_dot.isdigit() and not post_dot.isdigit():
                return False
            elif pre_dot.isdigit() and  post_dot == '':
                return True
            elif pre_dot== '' and  post_dot.isdigit():
                return True
            elif pre_dot.isdigit() and  post_dot.isdigit():
                return True

        return s.isdigit() #此时只包含第一部分
【方法2】:参考 https://zhuanlan.zhihu.com/simons/20042325https://www.cnblogs.com/zuoyuan/p/3703075.html

构建以下的DFA:

  • 0 初始无输入或者只有space的状态
  • 1 输入了数字之后的状态
  • 2 前面无数字,只输入了dot的状态
  • 3 输入了+/-状态
  • 4 前面有数字和有dot的状态
  • 5 'e' or 'E'输入后的状态
  • 6 输入e之后输入+/-的状态
  • 7 输入e后输入数字的状态
  • 8 前面有有效数输入之后,输入space的状态

只有1,4,7,8四种状态是合法的

【Python代码】:

    def isNumber2(self, s):
        INVALID = 0
        SPACE = 1
        SIGN = 2
        DIGIT = 3
        DOT = 4
        EXPONENT = 5
        # transitionTable 表示邻接矩阵,行表示的是0-8九个状态,列表示的是五种不同的输入,邻接矩阵中的值表示在不同的状态下接受不同的输入会达到怎样的状态,如transitionTable[0][0]此时在图中第0种状态 (no input or just spaces)时,若输入的值是INVALID,则值为-1,表示无效。若transitionTable[1][3]表示此时在图中第1种状态(input is digit)时,输入的值为DIGIT,则会跳转到图中第4种状态(digits and dot in front)

        transitionTable = [[-1,0,3,1,2,-1],           #0 no input or just spaces
                         [-1,  8, -1,  1,  4,  5],    #1 input is digits
                         [-1, -1, -1,  4, -1, -1],    #2 no digits in front just Dot
                         [-1, -1, -1,  1,  2, -1],    #3 sign
                         [-1,  8, -1,  4, -1,  5],    #4 digits and dot in front
                         [-1, -1,  6,  7, -1, -1],    #5 input 'e' or 'E'
                         [-1, -1, -1,  7, -1, -1],    #6 after 'e' input sign
                         [-1,  8, -1,  7, -1, -1],    #7 after 'e' input digits
                         [-1,  8, -1, -1, -1, -1]]    #8 after valid input input space
        state = 0
        for c in s:
            inputtype = INVALID
            if c == ' ':
                inputtype = SPACE
            elif c in ['+', '-']:
                inputtype = SIGN
            elif c.isdigit():
                inputtype = DIGIT
            elif c == '.':
                inputtype = DOT
            elif c in ['e', 'E']:
                inputtype = EXPONENT

            state = transitionTable[state][inputtype]
            if state == -1:
                return False

        return state == 1 or state == 4 or state == 7 or state == 8





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值