有效数字
有效数字

有效数字

Date
Jun 11, 2023
Created
Oct 15, 2023 05:52 PM
Tags
LeetCode
Algorithm
Java
Python
TypeScript
JavaScript
C#
C
Problem: 65.有效数字

构造DFA状态转换表

  1. 写出正规式。
    1. d = 0|1|2|3|4|5|6|7|8|9 (-|+|)(dd*(.d*|)|d*.dd*)((e|E)(-|+|)dd*|)
  1. 根据正规式画出 NFA
    1. -|+|ε
      dd*(.d*|)|d*.dd*
      (e|E)(-|+|ε)dd*|ε
      0
      1
      2
      3
      nfa
      -
      +
      ε
      dd*(.d*|)
      d*.dd*
      (e|E)(-|+|ε)dd*
      ε
      0
      1
      2
      3
      -
      +
      ε
      dd*
      .d*
      ε
      d*.dd*
      e|E
      -|+|ε
      dd*
      ε
      0
      1
      2
      3
      1_1
      2_1
      2_2
      -
      +
      ε
      d
      d
      ε
      .
      d
      ε
      ε
      ε
      d
      .
      d
      d
      ε
      e
      E
      -
      +
      ε
      d
      d
      ε
      ε
      0
      1
      2
      3
      1_1_1
      1_1
      1_1_2
      1_2
      1_3
      1_4
      2_1
      2_2
      2_2_1
      -
      +
      ε
      d
      d
      ε
      .
      d
      ε
      ε
      ε
      d
      .
      d
      d
      ε
      e
      E
      -
      +
      ε
      d
      d
      ε
      ε
      0
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
  1. NFA 确定化(NFA \rightarrow DFA)。
    1. -
      +
      d
      .
      e
      E
      {0,1,5}
      {1,5}
      {1,5}
      {2,3,5,8,12}
      {6}
      {1,5}A
      {2,3,5,8,12}
      {6}
      {2,3,5,8,12}B*
      {2,3,5,8,12}
      {4,6,8,12}
      {9,10}
      {9,10}
      {6}C
      {7,8,12}
      {4,6,8,12}D*
      {4,7,8,12}
      {9,10}
      {9,10}
      {9,10}E
      {10}
      {10}
      {11,12}
      {7,8,12}F*
      {7,8,12}
      {9,10}
      {9,10}
      {4,7,8,12}G*
      {4,7,8,12}
      {9,10}
      {9,10}
      {10}H
      {11,12}
      {11,12}I*
      {11,12}
  1. DFA 最小化(已无法最小化)。

表驱动法具体实现

  1. 写出 DFA 状态转换表。
    1. '-'
      '+'
      '0'-'9'
      '.'
      'e'
      'E'
      A
      A
      B*
      C
      A
      B*
      C
      B*
      B*
      D*
      E
      E
      C
      F*
      D*
      G*
      E
      E
      E
      H
      H
      I*
      F*
      F*
      E
      E
      G*
      G*
      E
      E
      H
      I*
      I*
      I*
  1. 各状态对于 -/+e/E 的转换动作一致,为了节省数组空间,对该表进一步简化。
    1. '-'/'+'
      '0'-'9'
      '.'
      'e'/'E'
      A
      B*
      C
      A
      B*
      C
      B*
      B*
      D*
      E
      C
      F*
      D*
      G*
      E
      E
      H
      I*
      F*
      F*
      E
      G*
      G*
      E
      H
      I*
      I*
      I*

代码

Java
class Solution { public boolean isNumber(String s) { int[][] dfaTable = new int[][] { {1, 2, 3, -1}, {-1, 2, 3, -1}, {-1, 2, 4, 5}, {-1, 6, -1, -1}, {-1, 7, -1, 5}, {8, 9, -1, -1}, {-1, 6, -1, 5}, {-1, 7, -1, 5}, {-1, 9, -1, -1}, {-1, 9, -1, -1} }; int[] endOfStates = new int[] { 2, 4, 6, 7, 9 }; int state = 0; for (int i = 0; i < s.length() && state != -1; i++) { int charIndex = getCharIndex(s.charAt(i)); if (charIndex == -1) { return false; } state = dfaTable[state][charIndex]; } for (int i = 0; i < endOfStates.length; i++) { if (state == endOfStates[i]) { return true; } } return false; } int getCharIndex(char c) { if (c == '-' || c == '+') { return 0; } else if (c >= '0' && c <= '9') { return 1; } else if (c == '.') { return 2; } else if (c == 'e' || c == 'E') { return 3; } else { return -1; } } }
Python3
class Solution: def isNumber(self, s: str): dfaTable = [ [1, 2, 3, -1], [-1, 2, 3, -1], [-1, 2, 4, 5], [-1, 6, -1, -1], [-1, 7, -1, 5], [8, 9, -1, -1], [-1, 6, -1, 5], [-1, 7, -1, 5], [-1, 9, -1, -1], [-1, 9, -1, -1] ] endOfStates = [ 2, 4, 6, 7, 9 ] state = 0 for c in s: charIndex = self.getCharIndex(c) if charIndex == -1: return False state = dfaTable[state][charIndex] if state == -1: break for endOfState in endOfStates: if state == endOfState: return True return False def getCharIndex(self, c: str): if c == '-' or c == '+': return 0 elif c >= '0' and c <= '9': return 1 elif c == '.': return 2 elif c == 'e' or c == 'E': return 3 else: return -1
TypeScript
var isNumber = (s: string) => { const dfaTable = [ [1, 2, 3, -1], [-1, 2, 3, -1], [-1, 2, 4, 5], [-1, 6, -1, -1], [-1, 7, -1, 5], [8, 9, -1, -1], [-1, 6, -1, 5], [-1, 7, -1, 5], [-1, 9, -1, -1], [-1, 9, -1, -1] ]; const endOfStates = [ 2, 4, 6, 7, 9 ]; let state = 0; for (let i = 0; i < s.length && state != -1; i++) { const charIndex = getCharIndex(s.charAt(i)); if (charIndex == -1) { return false; } state = dfaTable[state][charIndex]; } for (let i = 0; i < endOfStates.length; i++) { if (state == endOfStates[i]) { return true; } } return false; } var getCharIndex = (c: string) => { if (c == '-' || c == '+') { return 0; } else if (c >= '0' && c <= '9') { return 1; } else if (c == '.') { return 2; } else if (c == 'e' || c == 'E') { return 3; } else { return -1; } }
JavaScript
var isNumber = (s) => { const dfaTable = [ [1, 2, 3, -1], [-1, 2, 3, -1], [-1, 2, 4, 5], [-1, 6, -1, -1], [-1, 7, -1, 5], [8, 9, -1, -1], [-1, 6, -1, 5], [-1, 7, -1, 5], [-1, 9, -1, -1], [-1, 9, -1, -1] ]; const endOfStates = [ 2, 4, 6, 7, 9 ]; let state = 0; for (let i = 0; i < s.length && state != -1; i++) { const charIndex = getCharIndex(s.charAt(i)); if (charIndex == -1) { return false; } state = dfaTable[state][charIndex]; } for (let i = 0; i < endOfStates.length; i++) { if (state == endOfStates[i]) { return true; } } return false; } var getCharIndex = (c) => { if (c == '-' || c == '+') { return 0; } else if (c >= '0' && c <= '9') { return 1; } else if (c == '.') { return 2; } else if (c == 'e' || c == 'E') { return 3; } else { return -1; } }
C#
public class Solution { public bool IsNumber(String s) { int[][] dfaTable = new int[][] { new int[] {1, 2, 3, -1}, new int[] {-1, 2, 3, -1}, new int[] {-1, 2, 4, 5}, new int[] {-1, 6, -1, -1}, new int[] {-1, 7, -1, 5}, new int[] {8, 9, -1, -1}, new int[] {-1, 6, -1, 5}, new int[] {-1, 7, -1, 5}, new int[] {-1, 9, -1, -1}, new int[] {-1, 9, -1, -1} }; int[] endOfStates = new int[] { 2, 4, 6, 7, 9 }; int state = 0; for (int i = 0; i < s.Length && state != -1; i++) { int charIndex = GetCharIndex(s[i]); if (charIndex == -1) { return false; } state = dfaTable[state][charIndex]; } for (int i = 0; i < endOfStates.Length; i++) { if (state == endOfStates[i]) { return true; } } return false; } int GetCharIndex(char c) { if (c == '-' || c == '+') { return 0; } else if (c >= '0' && c <= '9') { return 1; } else if (c == '.') { return 2; } else if (c == 'e' || c == 'E') { return 3; } else { return -1; } } }
C
int getCharIndex(char c) { if (c == '-' || c == '+') { return 0; } else if (c >= '0' && c <= '9') { return 1; } else if (c == '.') { return 2; } else if (c == 'e' || c == 'E') { return 3; } else { return -1; } } bool isNumber(char* s) { int dfaTable[10][4] = { {1, 2, 3, -1}, {-1, 2, 3, -1}, {-1, 2, 4, 5}, {-1, 6, -1, -1}, {-1, 7, -1, 5}, {8, 9, -1, -1}, {-1, 6, -1, 5}, {-1, 7, -1, 5}, {-1, 9, -1, -1}, {-1, 9, -1, -1} }; int endOfStates[5] = { 2, 4, 6, 7, 9 }; int state = 0; for (int i = 0; i < strlen(s) && state != -1; i++) { int charIndex = getCharIndex(*(s + i)); if (charIndex == -1) { return false; } state = dfaTable[state][charIndex]; } for (int i = 0; i < sizeof(endOfStates) / sizeof(int); i++) { if (state == endOfStates[i]) { return true; } } return false; }

复杂度分析

  • 时间复杂度:O(n)O(n)n=s.lengthn=s.length
  • 空间复杂度:O(n)O(n)n=s.lengthn=s.length