In the Leetcode Valid Number problem solution A valid number can be split up into these components (in order):
A decimal number or an integer.
(Optional) An ‘e’ or ‘E’, followed by an integer.
A decimal number can be split up into these components (in order):
(Optional) A sign character (either ‘+’ or ‘-‘).
One of the following formats:
One or more digits, followed by a dot ‘.’.
One or more digits, followed by a dot ‘.’, followed by one or more digits.
A dot ‘.’, followed by one or more digits.
An integer can be split up into these components (in order):
(Optional) A sign character (either ‘+’ or ‘-‘).
One or more digits.
For example, all the following are valid numbers: [“2”, “0089”, “-0.1”, “+3.14”, “4.”, “-.9”, “2e10”, “-90E3”, “3e+7”, “+6e-1”, “53.5e93”, “-123.456e789”], while the following are not valid numbers: [“abc”, “1a”, “1e”, “e3”, “99e2.5”, “–6”, “-+3”, “95a54e53”].
Given a string s, return true if s is a valid number.
Example 1:
Input: s = “0”
Output: true
Example 2:
Input: s = “e”
Output: false
Example 3:
Input: s = “.”
Output: false
Constraints:
- 1 <= s.length <= 20
- s consists of only English letters (both uppercase and lowercase), digits (0-9), plus ‘+’, minus ‘-‘, or dot ‘.’.
Solution in C Programming
char transitionTable[8][4] = {
{2, 0, 3, 4},
{2, 5, 6, 0},
{6, 0, 0, 0},
{2, 0, 3, 0},
{7, 0, 0, 8},
{6, 5, 0, 0},
{7, 0, 0, 0},
{7, 0, 0 ,0},
};
enum token {
digit = 0,
exponential = 1,
dot = 2,
sign = 3,
};
bool isNumber(char * s){
char state = 1;
for (int i = 0; s[i]; i++) {
switch(s[i]) {
case '0' ... '9':
if (state = transitionTable[state-1][digit]) continue; else return false;
case 'e':
case 'E':
if (state = transitionTable[state-1][exponential]) continue; return false;
case '.':
if (state = transitionTable[state-1][dot]) continue; else return false;
case '+':
case '-':
if (state = transitionTable[state-1][sign]) continue; else return false;
default:
return false;
}
}
return state == 2 || state == 6 || state == 7;
}
Solution in C++ Programming
class Solution {
public:
bool isNumber(string s) {
int len=s.length();
int en=0,dot=0,sign=0;
for(int i=0;i<len;i++)
{
if(s[i]=='+' or s[i]=='-'){
if(i!=0 and !(s[i-1]=='e' or s[i-1]=='E'))
return false;
if(en==0 and sign) return false;
else sign++;
}
else if(s[i]=='.')
{
bool dg=false;
if(en) return false;
if(i!=0 and i==len and s[i-1]>=48 and s[i-1]<=57)
dg=true;
else if(i!=len-1 and i==0 and s[i+1]>=48 and s[i+1]<=57)
dg=true;
else if(i>0 and i<len and (s[i-1]>=48 and s[i-1]<=57) or (s[i+1]>=48 and s[i+1]<=57))
dg=true;
if(!dg)
return false;
dot++;
}
else if(s[i]=='e' or s[i]=='E')
{
if(i==len-1 or i==0) return false;
if(s[i+1]=='+' or s[i+1]=='-')
{
if(i+1==len-1) return false;
if(s[i+2]<48 or s[i+2]>57) return false;
}
else if(s[i+1]<48 or s[i+1]>57 or s[i-1]=='+' or s[i-1]=='-') return false;
en++;
}
else if(s[i]>=48 and s[i]<=57)
continue;
else
return false;
}
if(dot>1 or sign>2 or en>1)
return false;
return true;
}
};
Solution in Java Programming
class Solution {
public boolean isNumber(String s) {
return s.trim().matches("^[+-]?("
+ "(\\d+(\\.\\d*)?(e[+-]?\\d+)?)"
+ "|((\\.\\d+)(e[+-]?\\d+)?))$");
}
}
Solution in Python Programming
import re
pattern = re.compile(r"^ *[-+]?([0-9]+|([0-9]*\.[0-9]+)|([0-9]+\.[0-9]*))(e[+-]?[0-9]+)? *$")
class Solution:
def isNumber(self, s):
return pattern.match(s)
Solution in C# Programming
public class Solution {
public bool IsNumber(string s) {
var parser = new NumberParser(s);
return parser.MatchNumber();
}
}
public class NumberParser {
private Parser parser;
public NumberParser(string s) {
this.parser = new Parser(s);
}
public bool MatchNumber() {
var res = MatchSinificand();
if (!res) {
return false;
}
MatchExponent();
if (parser.End) {
return true;
}
return false;
}
private bool MatchExponent() {
var pos = parser.Pos;
var res = parser.Match(new[] { "e", "E" });
if (res) {
var res2 = MatchInteger();
if (res2) {
return true;
}
}
parser.Pos = pos;
return false;
}
private bool MatchSinificand() {
var pos = parser.Pos;
bool res = MatchDecimal();
if (res) {
return true;
}
parser.Pos = pos;
res = MatchInteger();
if (res) {
return true;
}
parser.Pos = pos;
return false;
}
private bool MatchDigits() {
var pos = parser.Pos;
int digitCount = 0;
while (char.IsDigit(parser.Current) && !parser.End) {
digitCount++;
parser.MoveNext();
}
if (digitCount > 0) {
return true;
}
parser.Pos = pos;
return false;
}
private bool MatchInteger() {
var pos = parser.Pos;
var signTerms = new[] { "+", "-" };
parser.Match(signTerms);
var res = MatchDigits();
if (res) {
return true;
}
parser.Pos = pos;
return false;
}
private bool MatchDecimal() {
var pos = parser.Pos;
var signTerms = new[] { "+", "-" };
parser.Match(signTerms);
var pos2 = parser.Pos;
if (MatchDigits() && parser.Match(new[] { "." }) && MatchDigits()) {
return true;
}
parser.Pos = pos2;
if (MatchDigits() && parser.Match(new[] { "." })) {
return true;
}
parser.Pos = pos2;
if (parser.Match(new[] { "." }) && MatchDigits()) {
return true;
}
parser.Pos = pos;
return false;
}
}
public class Parser {
public string Source { get; init; }
public int Pos { get; set; } = 0;
public char this[int index] {
get { return index < this.Source.Length ? Source[index] : (char)0; }
}
public char Current {
get { return this[Pos]; }
}
public bool End {
get { return Current == 0; }
}
public Parser(string src) {
this.Source = src;
}
public void MoveNext() {
if (!this.End) {
Pos++;
}
}
public bool Match(string[] terms) {
var pos = this.Pos;
foreach (var term in terms) {
bool match = true;
foreach (var c in term) {
if (this.Current == c) {
this.MoveNext();
}
else {
this.Pos = pos;
match = false;
break;
}
}
if (match) {
return true;
}
}
Pos = pos;
return false;
}
}
Also read,