【LeetCode】面试题20. 表示数值的字符串

题目:

思路:

1、分析规律,逻辑判断,需要特别注意特殊情况。
2、确定有限自动机(DFA)。构造DFA可以先写正则表达式再转换成DFA,也可以直接写。如下图所示DFA中红色为终止状态,蓝色为中间状态。DFA从状态0开始接收字符,当输入字符结束时当前状态处于中间状态,则拒绝;如果到达终止状态,则接受。状态0和8用于处理开始和结束时的空格。

红色的3个终止状态分别表示小数点前的数字、小数点后的数字、e后的数字。同样都是数字但是位置不同,不是一个状态。比如小数点前的数字可以转移到小数点,但是小数点后的数字无法转移到小数点。

' ' '+/-' '0-9' '.' 'e/E' other
0 0 1 6 2 -1 -1
1 -1 -1 6 2 -1 -1
2 -1 -1 3 -1 -1 -1
3 8 -1 3 -1 4 -1
4 -1 7 5 -1 -1 -1
5 8 -1 5 -1 -1 -1
6 8 -1 6 3 4 -1
7 -1 -1 5 -1 -1 -1
8 8 -1 -1 -1 -1 -1

代码:

Python

class Solution(object):
    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        point = -1
        e = -1
        s = s.strip(' ')
        if len(s) == 0:
            return False
        firstNum = -1
        for i in range(len(s)):
            # +/-只能出现在第一个字符或e之后, 但不能是最后一个字符
            if s[i] in ['+', '-']:
                if (i != 0 and s[i-1] not in ['e', 'E']) or i == len(s) - 1:
                    return False
            elif s[i] == '.':
                # .前面出现过.||.前没有数字且是最后一个字符, False
                if point != -1 or (firstNum == -1 and i == len(s) - 1):
                    return False
                else:
                    point = i
            elif s[i] in ['e', 'E']:
                # e是第一个或最后一个字符||e前面出现过e||e前面没有数字, False
                if i == 0 or i == len(s) - 1 or e != -1 or firstNum == -1:
                    return False
                # 出现过e, 且e之后不能出现.
                else:
                    e = i
                    point = i
            elif '0' <= s[i] <= '9':
                if firstNum == -1:
                    firstNum = i
                continue
            else:
                return False
        return True
class Solution(object):
    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        numSeen = False
        dotSeen = False
        eSeen = False
        # 去掉前后的空格
        s = s.strip(' ')
        if len(s) == 0:
            return False
        for i in range(len(s)):
            if '0' <= s[i] <= '9':
                numSeen = True
            # .之前不能出现.和e
            elif s[i] == '.':
                if dotSeen or eSeen:
                    return False
                else:
                    dotSeen = True
            # e之前不能出现e, 且必须出现数字
            elif s[i] in ['e', 'E']:
                if eSeen or not numSeen:
                    return False
                else:
                    eSeen = True
                    numSeen = False  # e之后也要出现数字
            elif s[i] in ['-', '+']:
                if i != 0 and s[i-1] not in ['e', 'E']:
                    return False
            else:
                return False
        return numSeen
class Solution(object):
    def getIndex(self, c):
        myIndex = {
            ' ': 0, 
            '+': 1, 
            '-': 1, 
            'num': 2, 
            '.': 3, 
            'e': 4, 
            'E': 4}
        if '0' <= c <= '9':
            return myIndex.get('num')
        else:
            return myIndex.get(c, -1)
    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        state = 0
        finals = 0b101101000 # 终止状态3/5/6/8
        transfer = [
            [0, 1, 6, 2, -1], 
            [-1, -1, 6, 2, -1],
            [-1, -1, 3, -1, -1],
            [8, -1, 3, -1, 4],
            [-1, 7, 5, -1, -1],
            [8, -1, 5, -1, -1],
            [8, -1, 6, 3, 4],
            [-1, -1, 5, -1, -1],
            [8, -1, -1, -1, -1]]
        for c in s:
            id = self.getIndex(c)
            if id < 0:
                return False
            state = transfer[state][id]
            if state < 0:
                return False
        # 1 << state表示1向左移动state位
        return (finals & (1 << state)) > 0

相关问题

posted @ 2020-06-01 16:51  一只背影  阅读(200)  评论(0编辑  收藏  举报