Valid Number

Validate if a given string is numeric.

Some examples:
“0” => true
” 0.1 ” => true
“abc” => false
“1 a” => false
“2e10” => true
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.

这道题就是将所有的情况都想出来,然后按条件写好即可
我们首先trim掉头尾的空格,和开头的+和-
然后剩下的所有字符里只能有. e +/-最多各一个和其他的数字
然后就是每种情况分别写好即可。注意e不可以开头结尾,.不可以结尾,还有其他的一些,他们之间的位置关系,列清楚即可通过

public class Solution {
    public boolean isNumber(String s) {
        s = s.trim(); // remove trailing and heading spaces
        if (s.length() == 0)
            return false;
        StringBuilder in = new StringBuilder(s);
        if ((s.charAt(0)) == '+' || (s.charAt(0) == '-')) // remove the head +/-
            in.deleteCharAt(0);
        int dot = -1;
        int e = -1;
        int sign = -1; // decimal point and e position and sign position
        for (int i = 0; i < in.length(); i++)
        {
            if (in.charAt(i) == '.' && dot == -1)
                dot = i;
            else if (in.charAt(i) == 'e' && e == -1)
                e = i;
            else if (in.charAt(i) =='-' || in.charAt(i) == '+')
                sign = i;
            else if (!Character.isDigit(in.charAt(i)))
                return false;
        }
        
        if (dot == -1 && e == -1 && sign == -1) //xxx
        {
            return true;
        }
        else if (dot != -1 && e == -1 && sign == -1 ) //xxx.xxx
        {
            if (dot == 0 && in.length() == 1) //xxx. is legal, but . itself is not
                return false;
            return true;
        }
        else if (dot == -1 && e != -1 && sign == -1) //xxexx
        {
            if ( e == in.length() - 1 || e == 0) //xxe is not legal
                return false;
            return true;
        }
        else if (dot != -1 && e != -1 && sign == -1)
        {
            if ((dot == 0 && dot == e-1) || dot == in.length() - 1 || e == in.length() - 1 || e == 0 || dot > e) // xx.e is not legal .exxx is not legal
                return false;
            return true;
        }
        else if (dot != -1 && e != -1 && sign != -1)
        {
            if (dot == in.length() - 1 || e == in.length() -1 || sign != e+1 || sign == in.length() - 1 || e == 0)
                return false;
            return true;
        }
        else if (dot == -1 && e != -1 && sign != -1)
        {
            if (sign != e+1 || sign == in.length() - 1 || e == 0)
                return false;
            return true;
        }
        else
            return false;
    }
}

Second Submission:
Use regular expression, but be careful with the matching

public class Solution {
    public boolean isNumber(String s) {
      String regex = "[-+]?((\\d+\\.?)|(\\d*\\.?\\d+))(e[+-]?\\d+)?";
      return s.trim().matches(regex);
    }
}
public class Solution {
    public boolean isNumber(String s) {
        s = s.trim(); // remove the heading and trailing space
        if (s.length() == 0)
            return false;
        if (s.charAt(0) == '-' || s.charAt(0) == '+')
            s = s.substring(1);
        if (s.length() == 0)
            return false;
        // find the position of . and e
        int dot = -1;
        int e = -1;
        int sign = -1; //
        for (int i = 0; i < s.length(); i++) {
            if (!Character.isDigit(s.charAt(i))) {
                if (s.charAt(i) == '.') {
                    if (dot == -1)
                        dot = i;
                    else
                        return false; // can not be more than one .
                    continue;
                } 
                if (s.charAt(i) == 'e') {
                    if (e == -1)
                        e = i;
                    else
                        return false; // can not be more than one e
                    continue;
                }
                if (s.charAt(i) == '+' || s.charAt(i) == '-') {//xx.xxe+/-xx
                    if (e != -1 && i == e+1) {
                        continue;
                    }
                }
                return false;
            }
        }
        if (dot == -1 && e == -1) //XXX all numbers 
            return true;
        if (dot != -1 && e == -1) {//XXX.XXX
            if (s.length() == 1)
                return false;
        }
        if (dot == -1 && e != -1) { //XXXeXXX
            if (e == 0 || e == s.length()-1)
                return false;
            if (s.charAt(e+1) == '-' || s.charAt(e+1) == '+') { //xxe+xx
                if (e+1 == s.length() - 1)
                    return false;
            }
        }
        if (dot != -1 && e != -1) {//XXX.XXeXX
            if (dot > e || e == s.length() - 1) // XXXeX. XX.Xe
                return false;
            if (dot == 0 && dot == e-1)
                return false;
            if (s.charAt(e+1) == '-' || s.charAt(e+1) == '+') { //x.xe+xx
                if (e+1 == s.length() - 1)
                    return false;
            }
        }
        return true;
    }
}

A cleaner answer: skip the possible spaces, Signs, digits and . and e in proper order.

public class Solution {
    public boolean isNumber(String s) {
        if (s.length() == 0)
            return false;
        int start = 0;
        start += skipSpaces(s, start); //skip space if exist
        if (start == s.length()) //the string has only " " characters
            return false;
        start += skipSign(s, start);
        int d1 = skipDigits(s, start);
        start += d1;
        if (start == s.length()) // xxx only
            return true;
        if (s.charAt(start) == '.') //xxx.xx
            start++;
        int d2 = skipDigits(s, start);
        start += d2;
        if (d1 == 0 && d2 == 0)
            return false;
        if (start == s.length()) // xxx.xx
            return true;
        if (s.charAt(start) == 'e' || s.charAt(start) == 'E') {//xxxexxx
            start++;
            start += skipSign(s, start);
            int d3 = skipDigits(s, start);
            if (d3 == 0)
                return false;
            start += d3;
        }
        
        start += skipSpaces(s, start);
        return (start == s.length());
    }
    
    public int skipSign(String s, int start) {
        if (start < s.length() && (s.charAt(start) == '+' || s.charAt(start) == '-'))
            return 1;
        return 0;
    } 
    
    public int skipDigits(String s, int start) {
        int len = 0;
        while (start < s.length() && Character.isDigit(s.charAt(start))) {
            len++;
            start++;
        }
        return len;
    }
    
    public int skipSpaces(String s, int start) {
        //increment until space was not found
        int len = 0;
        while(start < s.length() && (s.charAt(start) == ' ')) {
            len++;
            start++;
        }
        return len;
    }
}

Leave a comment