Talentd
FleetCode
Make and follow sheets.Sign in

Valid Number solution and explanation

HardString7 min read23.3% acceptanceUpdated 9 Apr 2026
Valid Number | Live Coding with Explanation | Leetcode - 65Algorithms Made Easy · 11:33 · 12K viewsWatch on YouTube
9 more videos on this problem
  1. Valid Number | Live Coding with Explanation | Leetcode - 65Algorithms Made Easy · 11:33 · 12K views
  2. VALID NUMBER | LEETCODE #65 | PYTHON SOLUTIONCracking FAANG · 18:18 · 10K views
  3. LeetCode 65. Valid Number Explanation and Solutionhappygirlzt · 6:04 · 6K views
  4. [Leetcode 65] Valid NumberbasketwangCoding · 10:07 · 2K views
  5. Leetcode 65 Valid NumberRen Zhang · 38:56 · 1K views
  6. Valid Number | Leetcode 65 | Leetcode Hard | Live coding sessionCoding Decoded · 11:49 · 1K views
  7. Valid Number | LeetCode 65 | Coders CampCoders Camp · 11:05 · 1K views
  8. Leetcode 65 Valid NumberUday Singh · 9:39 · 917 views
  9. Leetcode 65 - Valid Number (Java)TheAnalyticGuy · 10:34 · 649 views
  10. 65. Valid Number - LeetCode HardLeetcodeHARD · 5:01 · 368 views

The problem

Given a string s, return whether s is a valid number.

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".

Formally, a valid number is defined using one of the following definitions:

  1. An integer number followed by an optional exponent.
  2. A decimal number followed by an optional exponent.

An integer number is defined with an optional sign '-' or '+' followed by digits.

A decimal number is defined with an optional sign '-' or '+' followed by one of the following definitions:

  1. Digits followed by a dot '.'.
  2. Digits followed by a dot '.' followed by digits.
  3. A dot '.' followed by digits.

An exponent is defined with an exponent notation 'e' or 'E' followed by an integer number.

The digits are defined as one or more digits.

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 '.'.

Approach overview

Problem Overview: Given a string, determine whether it represents a valid numeric value. The string may contain digits, optional sign characters (+ or -), decimal points, and scientific notation using e or E. The challenge is validating the structure of the number while handling edge cases like multiple signs, misplaced decimals, or incomplete exponent parts.

Approach 1: Using Regular Expressions (O(n) time, O(1) space)

This approach relies on a carefully constructed regular expression that describes all valid numeric formats. The pattern checks optional leading signs, digits before or after a decimal point, and an optional exponent part like e+10. Once the pattern is defined, you simply run a regex match against the input string. Regex engines scan the string in linear time, so the complexity is O(n), and the memory overhead is constant aside from the compiled pattern. This approach is concise and easy to implement, especially in languages with strong regex support such as Python, Java, and JavaScript. The tradeoff is readability—debugging a complex regex can be difficult during interviews.

Approach 2: Iterative Parsing Approach (O(n) time, O(1) space)

This method scans the string once while tracking key conditions using boolean flags. As you iterate through characters, maintain flags such as seenDigit, seenDot, and seenExponent. Digits are always allowed, but a decimal point can appear only once and only before an exponent. The exponent character (e or E) must appear after at least one digit and resets the requirement that digits must follow. Sign characters are allowed only at the start of the string or immediately after an exponent. By validating each character under these rules, you effectively implement a lightweight parser. This approach is deterministic, interview-friendly, and commonly expected when solving string parsing problems.

Edge cases handled by this scan include inputs like ".1", "3.", "-90E3", and invalid cases such as "1e", "e3", or multiple decimal points. The algorithm only performs a single pass through the string, making it optimal for large inputs.

Recommended for interviews: The iterative parsing approach is typically preferred. It demonstrates your ability to reason about state transitions while processing a string. Regex works well in production code and quick scripts, but interviewers often want to see explicit logic instead of relying on regular expressions. Mentioning both approaches shows breadth: regex for brevity and manual parsing for algorithmic clarity.

Approach 1: Using Regular Expressions

A regular expression can be used to validate if a string is a valid number by matching patterns that define valid numbers. This pattern matches integers with optional signs, decimals, and scientific notation.

import re  
def isNumber(s: str) -> bool:  
    pattern = "^[\+-]?((\d+\.?|\.\d)\d*)([eE][\+-]?\d+)?$"  
    return re.match(pattern, s) is not None  

# Example usage  
print(isNumber("53.5e93"))  # True  
print(isNumber("1a"))      # False
import java.util.regex.Pattern;  
import java.util.regex.Matcher;  

public class ValidNumber {  
    public static boolean isNumber(String s) {  
        Pattern pattern = Pattern.compile("^[\+-]?(\d+\.?|\.\d)\d*([eE][\+-]?\d+)?$");  
        Matcher matcher = pattern.matcher(s);  
        return matcher.matches();  
    }  
    public static void main(String[] args) {  
        System.out.println(isNumber("53.5e93")); // true  
        System.out.println(isNumber("1a")); // false  
    }  
}
#include <regex>  
#include <string>  
#include <iostream>  

bool isNumber(std::string s) {  
    std::regex pattern("^[\+-]?((\d+\.?|\.\d)\d*)([eE][\+-]?\d+)?$");  
    return std::regex_match(s, pattern);  
}  

int main() {  
  std::cout << isNumber("53.5e93") << std::endl; // 1  
  std::cout << isNumber("1a") << std::endl; // 0  
  return 0;  
}
function isNumber(s) {  
    const pattern = /^[\+-]?((\d+\.?|\.\d)\d*)([eE][\+-]?\d+)?$/;  
    return pattern.test(s);  
}  
console.log(isNumber('53.5e93'));  // true  
console.log(isNumber('1a'));  // false
#include <stdio.h>  
#include <regex.h>  
#include <stdbool.h>  

bool isNumber(const char *s) {  
    regex_t regex;  
    int reti;  
    // Regular expression for matching a valid number  
    reti = regcomp(&regex, "^[\+-]?((\d+\.?|\.\d)\d*)([eE][\+-]?\d+)?$", REG_EXTENDED);  
    if (reti) {  
        fprintf(stderr, "Could not compile regex\n");  
        return false;  
    }  
    // Execute regular expression  
    reti = regexec(&regex, s, 0, NULL, 0);  
    regfree(&regex);  
    return !reti;  
}  

int main() {  
  printf("%d\n", isNumber("53.5e93")); // 1  
  printf("%d\n", isNumber("1a")); // 0  
  return 0;  
}
using System;  
using System.Text.RegularExpressions;  

class ValidNumber {  
    public static bool IsNumber(string s) {  
        string pattern = "^[\+-]?((\d+\.?|\.\d)\d*)([eE][\+-]?\d+)?$";  
        return Regex.IsMatch(s, pattern);  
    }  
    public static void Main() {  
        Console.WriteLine(IsNumber("53.5e93")); // True  
        Console.WriteLine(IsNumber("1a")); // False  
    }  
}

Python's re module makes regular expression matching straightforward. We use it to verify whether the input string fits valid numerical patterns.

Complexity

Time Complexity: O(n)
Space Complexity: O(1)

Try this approach in the editor

Approach 2: Iterative Parsing Approach

This approach involves parsing the string based on its characters and their positions. By iterating through the string, the method confirms whether it forms a valid number pattern based on segment rules.

def isNumber(s: str) -> bool:  
    i, n = 0, len(s)  
    numSeen = dotSeen = eSeen = False  
    while i < n and s[i] == ' ': i += 1  
    if i < n and (s[i] == '+' or s[i] == '-'): i += 1  
    while i < n:  
        if s[i].isdigit():  
            numSeen = True  
        elif s[i] == '.':  
            if dotSeen or eSeen: return False  
            dotSeen = True  
        elif s[i] in 'eE':  
            if eSeen or not numSeen: return False  
            eSeen = True  
            numSeen = False  
        elif s[i] in '+-':  
            if s[i-1] not in 'eE': return False  
        elif s[i] == ' ':  
            while i < n and s[i] == ' ': i += 1  
            return i == n  
        else:  
            return False  
        i += 1  
    return numSeen  

print(isNumber("53.5e93"))  # True  
print(isNumber("1a"))      # False
public class ValidNumberIterative {  
    public static boolean isNumber(String s) {  
        int n = s.length();  
        int i = 0;  
        boolean numSeen = false, dotSeen = false, eSeen = false;  
        while (i < n && s.charAt(i) == ' ') i++;  
        if (i < n && (s.charAt(i) == '+' || s.charAt(i) == '-')) i++;  
        while (i < n) {  
            if (Character.isDigit(s.charAt(i))) {  
                numSeen = true;  
            } else if (s.charAt(i) == '.') {  
                if (dotSeen || eSeen) return false;  
                dotSeen = true;  
            } else if (s.charAt(i) == 'e' || s.charAt(i) == 'E') {  
                if (eSeen || !numSeen) return false;  
                eSeen = true;  
                numSeen = false;  
            } else if (s.charAt(i) == '+' || s.charAt(i) == '-') {  
                if (s.charAt(i-1) != 'e' && s.charAt(i-1) != 'E') return false;  
            } else if (s.charAt(i) == ' ') {  
                while (i < n && s.charAt(i) == ' ') i++;  
                return i == n;  
            } else {  
                return false;  
            }  
            i++;  
        }  
        return numSeen;  
    }  
    public static void main(String[] args) {  
        System.out.println(isNumber("53.5e93")); // true  
        System.out.println(isNumber("1a")); // false  
    }  
}
#include <iostream>  
#include <cctype>  
#include <string>  

bool isNumber(const std::string& s) {  
    int i = 0, n = s.length();  
    bool numSeen = false, dotSeen = false, eSeen = false;  
    while (i < n && s[i] == ' ') i++;  
    if (i < n && (s[i] == '+' || s[i] == '-')) i++;  
    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;  
        } else if (s[i] == '+' || s[i] == '-') {  
            if (s[i - 1] != 'e' && s[i - 1] != 'E') return false;  
        } else if (s[i] == ' ') {  
            while (i < n && s[i] == ' ') i++;  
            return i == n;  
        } else {  
            return false;  
        }  
        i++;  
    }  
    return numSeen;  
}  

int main() {  
  std::cout << isNumber("53.5e93") << std::endl; // true  
  std::cout << isNumber("1a") << std::endl; // false  
  return 0;  
}
function isNumber(s) {  
    let i = 0, n = s.length;  
    let numSeen = false, dotSeen = false, eSeen = false;  
    while (i < n && s[i] === ' ') i++;  
    if (i < n && (s[i] === '+' || s[i] === '-')) i++;  
    while (i < n) {  
        if (s[i] >= '0' && s[i] <= '9') {  
            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;  
        } else if (s[i] === '+' || s[i] === '-') {  
            if (s[i-1] !== 'e' && s[i-1] !== 'E') return false;  
        } else if (s[i] === ' ') {  
            while (i < n && s[i] === ' ') i++;  
            return i === n;  
        } else {  
            return false;  
        }  
        i++;  
    }  
    return numSeen;  
}  

console.log(isNumber('53.5e93')); // true  
console.log(isNumber('1a')); // false
#include <stdio.h>  
#include <stdbool.h>  
#include <ctype.h>  

bool isNumber(const char *s) {  
    int len = 0;  
    int i = 0;  
    bool numSeen = false, dotSeen = false, eSeen = false;  
    while (s[len]) len++;  
    // Skip leading spaces  
    while (s[i] == ' ') i++;  
    // Check for sign  
    if (s[i] == '+' || s[i] == '-') i++;  
    for (; i < len; i++) {  
        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;  
        } else if (s[i] == '+' || s[i] == '-') {  
            if (s[i - 1] != 'e' && s[i - 1] != 'E') return false;  
        } else if (s[i] == ' ') {  
            while (i < len && s[i] == ' ') i++;  
            return i == len;  
        } else {  
            return false;  
        }  
    }  
    return numSeen;  
}  

int main() {  
  printf("%d\n", isNumber("53.5e93")); // 1  
  printf("%d\n", isNumber("1a")); // 0  
  return 0;  
}
using System;  

class ValidNumberIterative {  
    public static bool IsNumber(string s) {  
        int n = s.Length;  
        int i = 0;  
        bool numSeen = false, dotSeen = false, eSeen = false;  
        while (i < n && s[i] == ' ') i++;  
        if (i < n && (s[i] == '+' || s[i] == '-')) i++;  
        while (i < n) {  
            if (char.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;  
            } else if (s[i] == '+' || s[i] == '-') {  
                if (s[i - 1] != 'e' && s[i - 1] != 'E') return false;  
            } else if (s[i] == ' ') {  
                while (i < n && s[i] == ' ') i++;  
                return i == n;  
            } else {  
                return false;  
            }  
            i++;  
        }  
        return numSeen;  
    }  

    public static void Main() {  
        Console.WriteLine(IsNumber("53.5e93")); // True  
        Console.WriteLine(IsNumber("1a")); // False  
    }  
}

This Python approach iterates through the string, ensuring all rules for a valid number are adhered to based on the position and current context of each character.

Complexity

Time Complexity: O(n)
Space Complexity: O(1)

Try this approach in the editor

Approach 3: Case Discussion

First, we check if the string starts with a positive or negative sign. If it does, we move the pointer i one step forward. If the pointer i has reached the end of the string at this point, it means the string only contains a positive or negative sign, so we return false.

If the character pointed to by the current pointer i is a decimal point, and there is no number after the decimal point, or if there is an e or E after the decimal point, we return false.

Next, we use two variables dot and e to record the number of decimal points and e or E respectively.

We use pointer j to point to the current character:

  • If the current character is a decimal point, and a decimal point or e or E has appeared before, return false. Otherwise, we increment dot by one;
  • If the current character is e or E, and e or E has appeared before, or if the current character is at the beginning or end of the string, return false. Otherwise, we increment e by one; then check if the next character is a positive or negative sign, if it is, move the pointer j one step forward. If the pointer j has reached the end of the string at this point, return false;
  • If the current character is not a number, return false.

After traversing the string, return true.

The time complexity is O(n), and the space complexity is O(1). Here, n is the length of the string.

func isNumber(s string) bool {
	i, n := 0, len(s)
	if s[i] == '+' || s[i] == '-' {
		i++
	}
	if i == n {
		return false
	}
	if s[i] == '.' && (i+1 == n || s[i+1] == 'e' || s[i+1] == 'E') {
		return false
	}
	var dot, e int
	for j := i; j < n; j++ {
		if s[j] == '.' {
			if e > 0 || dot > 0 {
				return false
			}
			dot++
		} else if s[j] == 'e' || s[j] == 'E' {
			if e > 0 || j == i || j == n-1 {
				return false
			}
			e++
			if s[j+1] == '+' || s[j+1] == '-' {
				j++
				if j == n-1 {
					return false
				}
			}
		} else if s[j] < '0' || s[j] > '9' {
			return false
		}
	}
	return true
}
impl Solution {
    pub fn is_number(s: String) -> bool {
        let mut i = 0;
        let n = s.len();

        if let Some(c) = s.chars().nth(i) {
            if c == '+' || c == '-' {
                i += 1;
                if i == n {
                    return false;
                }
            }
        }
        if let Some(x) = s.chars().nth(i) {
            if x == '.'
                && (i + 1 == n
                    || (if let Some(m) = s.chars().nth(i + 1) {
                        m == 'e' || m == 'E'
                    } else {
                        false
                    }))
            {
                return false;
            }
        }

        let mut dot = 0;
        let mut e = 0;
        let mut j = i;

        while j < n {
            if let Some(c) = s.chars().nth(j) {
                if c == '.' {
                    if e > 0 || dot > 0 {
                        return false;
                    }
                    dot += 1;
                } else if c == 'e' || c == 'E' {
                    if e > 0 || j == i || j == n - 1 {
                        return false;
                    }
                    e += 1;
                    if let Some(x) = s.chars().nth(j + 1) {
                        if x == '+' || x == '-' {
                            j += 1;
                            if j == n - 1 {
                                return false;
                            }
                        }
                    }
                } else if !c.is_ascii_digit() {
                    return false;
                }
            }
            j += 1;
        }

        true
    }
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Using Regular Expressions

Time Complexity: O(n)
Space Complexity: O(1)

Iterative Parsing Approach

Time Complexity: O(n)
Space Complexity: O(1)

Case Discussion–

Complexity analysis

ApproachTimeSpaceWhen to Use
Regular Expression MatchingO(n)O(1)When the language provides strong regex support and you want a concise validation rule
Iterative Parsing with FlagsO(n)O(1)Interview scenarios or when explicit validation logic is required

Frequently asked questions

Is Valid Number easy or hard?

Valid Number is classified as a Hard problem because of the large number of edge cases. The logic itself is straightforward once broken into rules, but ensuring all valid formats and rejecting invalid ones requires careful state tracking.

How to solve Valid Number in O(n)?

Traverse the string once while maintaining boolean flags such as seenDigit, seenDot, and seenExponent. Allow digits anywhere, allow a decimal only once before an exponent, and ensure an exponent appears only after at least one digit. Sign characters are valid only at the start or immediately after an exponent. This single-pass validation guarantees O(n) time complexity.

Valid Number Python or Java solution?

Both Python and Java solutions typically implement a single-pass parser with boolean flags. Python solutions may also use the re module for regex matching, while Java commonly uses character iteration with conditions. In both languages the optimal complexity remains O(n) time and O(1) space.

What is the best approach for Valid Number?

The iterative parsing approach is generally the best solution. It scans the string once while tracking rules for digits, decimal points, signs, and exponents using simple flags. This method runs in O(n) time and O(1) space and clearly demonstrates understanding of string parsing logic, which interviewers typically expect.

What data structure is used in Valid Number?

The problem mainly uses string traversal with a few boolean state variables. No complex data structures are required. The algorithm relies on parsing rules that track whether digits, decimal points, or exponent markers have already appeared.

What is the time complexity of Valid Number?

Both common solutions run in O(n) time where n is the length of the string. Each character is processed once either by the regex engine or a manual parsing loop. Space complexity is O(1) because only a few flags or a compiled pattern are stored.

Is Valid Number asked at Google, Amazon, or Meta?

Valid Number is a classic string parsing problem that has appeared in interviews at companies like Google, Amazon, and Meta. It tests careful handling of edge cases and state-based validation rather than heavy data structures or algorithms.

Comments

Now write it yourselfClose this page and solve Valid Number in the editor, without looking.
Practise Valid Number