Skip to content
本页目录

20-表示数值的字符串

题目描述

https://leetcode.cn/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。

数值(按顺序)可以分成以下几个部分:

若干空格 一个小数或者整数 (可选)一个'e'或'E',后面跟着一个整数 若干空格 小数(按顺序)可以分成以下几个部分:

(可选)一个符号字符('+' 或 '-') 下述格式之一: 至少一位数字,后面跟着一个点 '.' 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字 一个点 '.' ,后面跟着至少一位数字 整数(按顺序)可以分成以下几个部分:

(可选)一个符号字符('+' 或 '-') 至少一位数字 部分数值列举如下:

["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"] 部分非数值列举如下:

["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]

示例 1:

输入:s = "0"
输出:true

示例 2:

输入:s = "e"
输出:false

示例 3:

输入:s = "."
输出:false

示例 4:

输入:s = ".1"
输出:true

提示:

1 <= s.length <= 20 s 仅含英文字母(大写和小写),数字(0-9),加号 '+' ,减号 '-' ,空格 ' ' 或者点 '.' 。

思路【未完成】

  1. Trim 去掉首尾空格
  2. 判断全整型函数 IsUnsignInt(string s)

实现代码

csharp
public class Solution {

	private bool IsUnsignInt(string s, int start){
		for(int i=start; i<s.Length; i++){
			if(s[i] >= '0' && s[i] <= '9'){
			}
			else{
				return false;
			}
		}
		return true;
	}

	private bool IsInt(string s, int start){
		if(s[start] == '+' || s[start] == '-'){
			return IsUnsignInt(s,start+1);
		}
		else{
			return IsUnsignInt(s,start);
		}
	}

	private bool IsNumber(string s, int start){

	}
   
    public bool IsNumber(string s) {
     	s = s.Trim();
     	//判断首字母
     	return IsNumber(s,0);
    }
}

思路2:【官方:状态机】

csharp
public class Solution {
    public bool IsNumber(string s) {
        Dictionary<State, Dictionary<CharType, State>> transfer = new Dictionary<State, Dictionary<CharType, State>>();
        Dictionary<CharType, State> initialDictionary = new Dictionary<CharType, State> {
            {CharType.CHAR_SPACE, State.STATE_INITIAL},
            {CharType.CHAR_NUMBER, State.STATE_INTEGER},
            {CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT},
            {CharType.CHAR_SIGN, State.STATE_INT_SIGN}
        };
        transfer.Add(State.STATE_INITIAL, initialDictionary);
        Dictionary<CharType, State> intSignDictionary = new Dictionary<CharType, State> {
            {CharType.CHAR_NUMBER, State.STATE_INTEGER},
            {CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT}
        };
        transfer.Add(State.STATE_INT_SIGN, intSignDictionary);
        Dictionary<CharType, State> integerDictionary = new Dictionary<CharType, State> {
            {CharType.CHAR_NUMBER, State.STATE_INTEGER},
            {CharType.CHAR_EXP, State.STATE_EXP},
            {CharType.CHAR_POINT, State.STATE_POINT},
            {CharType.CHAR_SPACE, State.STATE_END}
        };
        transfer.Add(State.STATE_INTEGER, integerDictionary);
        Dictionary<CharType, State> pointDictionary = new Dictionary<CharType, State> {
            {CharType.CHAR_NUMBER, State.STATE_FRACTION},
            {CharType.CHAR_EXP, State.STATE_EXP},
            {CharType.CHAR_SPACE, State.STATE_END}
        };
        transfer.Add(State.STATE_POINT, pointDictionary);
        Dictionary<CharType, State> pointWithoutIntDictionary = new Dictionary<CharType, State> {
            {CharType.CHAR_NUMBER, State.STATE_FRACTION}
        };
        transfer.Add(State.STATE_POINT_WITHOUT_INT, pointWithoutIntDictionary);
        Dictionary<CharType, State> fractionDictionary = new Dictionary<CharType, State> {
            {CharType.CHAR_NUMBER, State.STATE_FRACTION},
            {CharType.CHAR_EXP, State.STATE_EXP},
            {CharType.CHAR_SPACE, State.STATE_END}
        };
        transfer.Add(State.STATE_FRACTION, fractionDictionary);
        Dictionary<CharType, State> expDictionary = new Dictionary<CharType, State> {
            {CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER},
            {CharType.CHAR_SIGN, State.STATE_EXP_SIGN}
        };
        transfer.Add(State.STATE_EXP, expDictionary);
        Dictionary<CharType, State> expSignDictionary = new Dictionary<CharType, State> {
            {CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER}
        };
        transfer.Add(State.STATE_EXP_SIGN, expSignDictionary);
        Dictionary<CharType, State> expNumberDictionary = new Dictionary<CharType, State> {
            {CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER},
            {CharType.CHAR_SPACE, State.STATE_END}
        };
        transfer.Add(State.STATE_EXP_NUMBER, expNumberDictionary);
        Dictionary<CharType, State> endDictionary = new Dictionary<CharType, State>() {
            {CharType.CHAR_SPACE, State.STATE_END}
        };
        transfer.Add(State.STATE_END, endDictionary);

        int length = s.Length;
        State state = State.STATE_INITIAL;

        for (int i = 0; i < length; i++) {
            CharType type = ToCharType(s[i]);
            if (!transfer[state].ContainsKey(type)) {
                return false;
            } else {
                state = transfer[state][type];
            }
        }
        return state == State.STATE_INTEGER || state == State.STATE_POINT || state == State.STATE_FRACTION || state == State.STATE_EXP_NUMBER || state == State.STATE_END;
    }

    CharType ToCharType(char ch) {
        if (ch >= '0' && ch <= '9') {
            return CharType.CHAR_NUMBER;
        } else if (ch == 'e' || ch == 'E') {
            return CharType.CHAR_EXP;
        } else if (ch == '.') {
            return CharType.CHAR_POINT;
        } else if (ch == '+' || ch == '-') {
            return CharType.CHAR_SIGN;
        } else if (ch == ' ') {
            return CharType.CHAR_SPACE;
        } else {
            return CharType.CHAR_ILLEGAL;
        }
    }

    enum State {
        STATE_INITIAL,
        STATE_INT_SIGN,
        STATE_INTEGER,
        STATE_POINT,
        STATE_POINT_WITHOUT_INT,
        STATE_FRACTION,
        STATE_EXP,
        STATE_EXP_SIGN,
        STATE_EXP_NUMBER,
        STATE_END
    }

    enum CharType {
        CHAR_NUMBER,
        CHAR_EXP,
        CHAR_POINT,
        CHAR_SIGN,
        CHAR_SPACE,
        CHAR_ILLEGAL
    }
}

思路3

首先去除空格,然后根据各个符号出现情况判断当前的数字是否合法。

参考代码

csharp
public class Solution {
    public bool IsNumber(string s) {
        // 思路,去除空格
        // 遍历 记录是否 遇到过 . e 数字等信息
        s = s.Trim();
        bool seenDot = false;
        bool seenE = false;
        bool seenNum = false;
        bool seenSign = false;
        //依次判断
        for(int i=0; i<s.Length; i++){
            char c = s[i];
            if(c >= '0' && c <= '9'){
                seenNum = true;
            }
            else if(c == '+' || c == '-'){ //符号位只能出现在首位或者前一位是E
                if(i!=0 && s[i-1] != 'E' && s[i-1] != 'e'){
                    return false;
                }
                seenSign = true;
            }
            else if(c == 'E' || c == 'e'){
                if(seenE || !seenNum){
                    return false;
                }
                seenE = true;
                seenNum = false; //注意遇到e的时候,因为后面必须要跟上数字,所以要把 seenNum 设置为 false
            }
            else if(c == '.'){
                if(seenDot || seenE){
                    return false;
                }
                seenDot = true;
            }
            else{
                return false;
            }
        }
        return seenNum;
    }
}

复习 : 20220611

csharp
public class Solution {

    private void ScanNumber(string s, ref int i, ref bool hasNumber){
        while(i < s.Length && s[i] >= '0' && s[i] <= '9'){
            hasNumber = true;
            i++;
        }
    }

    public bool IsNumber(string s) {
        int i = 0;
        //判断空格
        while(i<s.Length && s[i] == ' '){
            i++;
        }
        if(i == s.Length){
            return false;
        }
        //判断符号
        bool hasSign = false;
        if(s[i] == '+' || s[i] == '-'){
            hasSign = true;
            i++;
        }
        //判断数字
        bool hasNumber = false;
        ScanNumber(s,ref i,ref hasNumber);
        
        bool hasDot = false;
        //判断小数
        if(i<s.Length && i < s.Length && s[i] == '.'){
            hasDot = true;
            i++;
            ScanNumber(s,ref i,ref hasNumber);
        }
        
        //判断E
        bool hasE = false;
        if(i < s.Length && (s[i] == 'E' || s[i] == 'e') && hasNumber ){
            hasE = true;
            hasNumber = false;
            i++;
            ScanNumber(s,ref i,ref hasNumber);
            //判断符号
            bool hasESign = false;
            if(i<s.Length && (s[i] == '+' || s[i] == '-')){
                hasESign = true;
                hasNumber = false;
                i++;
            }
            ScanNumber(s,ref i,ref hasNumber);
        }

        while(i<s.Length && s[i] == ' '){
            i++;
        }
        
        return i == s.Length && hasNumber;
    }
}

Released under the MIT License.