Problem Statement:
Given a string, determine if it represents a valid number. A valid number can be any of the following:
- An integer (positive or negative).
- A floating-point number (positive or negative).
- A number with or without an exponent (e.g.,
1e10
).
The string may contain leading or trailing whitespace characters, and may include a decimal point and an exponent (denoted by e
or E
).
Input:
- A string
s
representing the number.
Output:
- Return
true
ifs
represents a valid number, otherwise returnfalse
.
Example 1:
Input: "123"
Output: true
Example 2:
Input: "3.14159"
Output: true
Example 3:
Input: "1e10"
Output: true
Example 4:
Input: "abc"
Output: false
Example 5:
Input: "1e"
Output: false
Approach:
The problem can be solved using state machine or regular expressions. The state machine is preferred here due to better control over transitions.
Steps:
- Trim the input: Remove leading and trailing whitespaces.
- Identify parts of the number:
- Handle optional leading signs (
+
or-
). - Handle the integer part (can be a sequence of digits).
- Handle the decimal point (optional, can have digits before or after it).
- Handle the exponent part (
e
orE
followed by an optional sign and then a sequence of digits).
- Handle optional leading signs (
- Validate based on structure:
- A valid number can have zero or one decimal point.
- The exponent part must have digits following it.
Time Complexity:
- Time Complexity: O(n), where n is the length of the input string.
- Space Complexity: O(1), since we’re not using any extra space that grows with the input size.
Code Implementation:
1. C:
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
bool isNumber(char* s) {
if (s == NULL) return false;
int i = 0, n = 0;
// Trim leading whitespace
while (s[i] == ' ') i++;
// Handle optional sign
if (s[i] == '+' || s[i] == '-') i++;
bool numSeen = false, dotSeen = false, eSeen = false;
// Process each character
while (s[i] != '\0') {
if (isdigit(s[i])) {
numSeen = true;
} else if (s[i] == '.') {
if (dotSeen || eSeen) return false;
dotSeen = true;
} else if (s[i] == 'e' || s[i] == 'E') {
if (eSeen || !numSeen) return false;
eSeen = true;
numSeen = false; // Reset numSeen after exponent
} else if (s[i] == '+' || s[i] == '-') {
if (s[i - 1] != 'e' && s[i - 1] != 'E') return false;
} else {
return false; // Invalid character
}
i++;
}
return numSeen;
}
int main() {
char s[] = "3.14159";
if (isNumber(s)) {
printf("Valid Number\n");
} else {
printf("Invalid Number\n");
}
return 0;
}
2. C++:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
bool isNumber(string s) {
int i = 0, n = s.length();
// Trim leading spaces
while (i < n && s[i] == ' ') i++;
if (i == n) return false;
bool numSeen = false, dotSeen = false, eSeen = false;
// Check each character
while (i < n) {
if (isdigit(s[i])) {
numSeen = true;
} else if (s[i] == '.') {
if (dotSeen || eSeen) return false;
dotSeen = true;
} else if (s[i] == 'e' || s[i] == 'E') {
if (eSeen || !numSeen) return false;
eSeen = true;
numSeen = false; // Reset numSeen after exponent
} else if (s[i] == '+' || s[i] == '-') {
if (s[i - 1] != 'e' && s[i - 1] != 'E') return false;
} else {
return false;
}
i++;
}
return numSeen;
}
int main() {
string s = "3.14";
if (isNumber(s)) {
cout << "Valid Number" << endl;
} else {
cout << "Invalid Number" << endl;
}
return 0;
}
3. Java:
public class ValidNumber {
public static boolean isNumber(String s) {
s = s.trim();
int n = s.length();
if (n == 0) return false;
boolean numSeen = false, dotSeen = false, eSeen = false;
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
numSeen = true;
} else if (c == '.') {
if (dotSeen || eSeen) return false;
dotSeen = true;
} else if (c == 'e' || c == 'E') {
if (eSeen || !numSeen) return false;
eSeen = true;
numSeen = false; // Reset numSeen after exponent
} else if (c == '+' || c == '-') {
if (i > 0 && s.charAt(i - 1) != 'e' && s.charAt(i - 1) != 'E') return false;
} else {
return false;
}
}
return numSeen;
}
public static void main(String[] args) {
String s = "3.14";
System.out.println(isNumber(s) ? "Valid Number" : "Invalid Number");
}
}
4. Python:
def isNumber(s: str) -> bool:
s = s.strip()
if not s:
return False
num_seen, dot_seen, e_seen = False, False, False
for i in range(len(s)):
char = s[i]
if char.isdigit():
num_seen = True
elif char == '.':
if dot_seen or e_seen:
return False
dot_seen = True
elif char == 'e' or char == 'E':
if e_seen or not num_seen:
return False
e_seen = True
num_seen = False # Reset numSeen after exponent
elif char == '+' or char == '-':
if i > 0 and s[i-1] not in ('e', 'E'):
return False
else:
return False
return num_seen
# Example Usage
s = "3.14"
print("Valid Number" if isNumber(s) else "Invalid Number")
5. C#:
using System;
public class Solution {
public bool IsNumber(string s) {
s = s.Trim();
if (string.IsNullOrEmpty(s)) return false;
bool numSeen = false, dotSeen = false, eSeen = false;
for (int i = 0; i < s.Length; i++) {
char c = s[i];
if (Char.IsDigit(c)) {
numSeen = true;
} else if (c == '.') {
if (dotSeen || eSeen) return false;
dotSeen = true;
} else if (c == 'e' || c == 'E') {
if (eSeen || !numSeen) return false;
eSeen = true;
numSeen = false; // Reset numSeen after exponent
} else if (c == '+' || c == '-') {
if (i > 0 && s[i - 1] != 'e' && s[i - 1] != 'E') return false;
} else {
return false;
}
}
return numSeen;
}
public static void Main() {
Solution solution = new Solution();
string s = "3.14";
Console.WriteLine(solution.IsNumber(s) ? "Valid Number" : "Invalid Number");
}
}
6. JavaScript:
function isNumber(s) {
s = s.trim();
if (s.length === 0) return false;
let numSeen = false, dotSeen = false, eSeen = false;
for (let i = 0; i < s.length; i++) {
let char = s[i];
if (/\d/.test(char)) {
numSeen = true;
} else if (char === '.') {
if (dotSeen || eSeen) return false;
dotSeen = true;
} else if (char === 'e' || char === 'E') {
if (eSeen || !numSeen) return false;
eSeen = true;
numSeen = false; // Reset numSeen after exponent
} else if (char === '+' || char === '-') {
if (i > 0 && (s[i-1] !== 'e' && s[i-1] !== 'E')) return false;
} else {
return false;
}
}
return numSeen;
}
// Example Usage
let s = "3.14";
console.log(isNumber(s) ? "Valid Number" : "Invalid Number");
Summary:
- The algorithm checks for leading whitespace and processes the string to validate the number format.
- The approach considers cases for integers, floating-point numbers, and numbers with exponents.
- The complexity is linear in the size of the input string, i.e., O(n).