Skip to main content

65.有效数字

标签: string

难度: Hard

通过率: 20.75%

原题链接: https://leetcode.com/problems/valid-number/description/

题目描述

给定一个字符串 ss ,返回 ss 是否是一个有效数字。有效数字的定义如下:

  • 表示一个整数的数字可以后接一个可选指数。
  • 一个十进制数字可以后接一个可选指数。

整数定义为一个可选的符号 '-' 或 '+',紧跟随的必须是一串数字。

十进制数字定义为一个可选的符号 '-' 或 '+',并遵循以下定义之一:

  • 数字后面跟随一个点 '.'。
  • 数字后面跟随一个点 '.',后面再跟随数字。
  • 一个点 '.' 后面直接跟随数字。

一个指数定义为指数符号 'e' 或 'E' 后跟一个整数。

数字定义为一个或多个数字。

解题思路

解决这个问题的主要思想是使用有限状态机(Finite State Machine, FSM)来验证字符串是否是一个有效数字。你需要逐个字符检查,并根据出现的字符转换状态。通过实现一个状态转换的完整流程,决定该字符串是否是一个有效数字。

以下是状态转换机的解释:

  1. 初始化状态,正在处理开头的符号。
  2. 正在读取整数或小数之前的部分数字。
  3. 确定小数点的位置并处理小数部分的数字输入。
  4. 处理科学计数法中的指数符号。
  5. 读取指数部分的数字。
  6. 提取任何后的无效字符。

根据对字符串进行遍历的过程来调整状态,最后检查状态是否能够保证字符串是一个有效数字。

代码实现

def isNumber(s: str) -> bool:
# 定义状态机的状态集合
state = [
{}, # dummy state 0
{'blank': 1, 'sign': 2, 'digit': 3, '.': 4}, # state 1: start, leading whitespace allowed
{'digit': 3, '.': 4}, # state 2: sign
{'digit': 3, '.': 5, 'e': 6, 'blank': 9}, # state 3: digit (integer part)
{'digit': 5}, # state 4: dot has been met, need at least one digit after it
{'digit': 5, 'e': 6, 'blank': 9}, # state 5: digit (fractional part)
{'sign': 7, 'digit': 8}, # state 6: e or E met
{'digit': 8}, # state 7: sign after e
{'digit': 8, 'blank': 9}, # state 8: digit after e
{'blank': 9} # state 9: trailing whitespaces allowed
]

current_state = 1

for char in s:
if char.isdigit():
transition = 'digit'
elif char in '+-':
transition = 'sign'
elif char in 'eE':
transition = 'e'
elif char == '.':
transition = '.'
elif char == ' ':
transition = 'blank'
else:
transition = '?' # illegal character

# Check the transition
if transition not in state[current_state]:
return False

# Change to next state
current_state = state[current_state][transition]

# Accepting states: 3, 5, 8, 9
return current_state in [3, 5, 8, 9]

复杂度分析

时间复杂度是 O(n)O(n),其中 nn 是字符串 ss 的长度。 空间复杂度是 O(1)O(1),因为只需要有限个状态变量来跟踪状态机的状态变化。