本问题对应的 leetcode 原文链接:剑指 Offer 20. 表示数值的字符串

问题描述

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

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

  1. 若干空格

  2. 一个 小数 或者 整数

  3. (可选)一个 'e''E' ,后面跟着一个 整数

  4. 若干空格

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

    1. (可选)一个符号字符('+''-'
    2. 下述格式之一:
      1. 至少一位数字,后面跟着一个点 '.'
      2. 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
      3. 一个点 '.' ,后面跟着至少一位数字

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

    1. (可选)一个符号字符('+''-'
    2. 至少一位数字

    部分数值列举如下:

  • ["+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),加号 '+' ,减号 '-' ,空格 ' ' 或者点 '.'

解题思路

视频讲解直达: 本题视频讲解

代码实现

class Solution {
    public boolean isNumber(String s) {
        //有限状态机
        // 2.小数点 3.E/e 4. 数字字符 5. -+
        if(s == null || s.length() <= 0){
            return false;
        }
        char[] res = s.trim().toCharArray();
        if(res.length <= 0) return false;

        int n = res.length;

        boolean is_dot = false;
        boolean is_e_or_E = false;
        boolean is_num = false;
        for(int i = 0; i < n; i++){
            if(res[i] >= '0' && res[i] <= '9'){
                is_num = true;
            } else if(res[i] == '.'){
                //-+ 8.  8.8  .8
                // 前面:不能有重复的小数点,也不能出现 e/E
                if(is_dot || is_e_or_E){
                    return false;
                }
                is_dot = true;
            } else if(res[i] == 'e' || res[i] == 'E'){
                // 前面必须要有一个数字 || 前面不能出现重复的 e/E
                if(is_e_or_E || !is_num){
                    return false;
                }
                is_e_or_E = true;
                is_num =false;//11E+ 11E
            } else if(res[i] == '-' || res[i] == '+'){
                if(i!=0 && res[i-1] != 'e' && res[i-1] != 'E'){
                    return false;
                }
            } else {
                return false;
            }
        }

        return is_num;
    }
}

Python

class Solution(object):
    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        # 有限状态机
        # 2.小数点 3.E/e 4.数字字符 5.-+
        if s == None or len(s) <= 0:
            return False
        res = s.strip()
        if len(res) <= 0:
            return False

        n = len(res)
        is_dot = False
        is_e_or_E = False
        is_num = False
        for i in range(n):
            if res[i] >= '0' and res[i] <= '9':
                is_num = True
            elif res[i] == '.':
                # -+ 8.  8.8  .8
                # 前面:不能有重复的小数点,也不能出现 e/E
                if is_dot or is_e_or_E:
                    return False
                is_dot = True
            elif res[i] == 'e' or res[i] == 'E':
                # 前面必须要有一个数字 || 前面不能出现重复的 e/E
                if is_e_or_E or not is_num:
                    return False
                is_e_or_E = True
                is_num = False #11E+ 11E
            elif res[i] == '-' or res[i] == '+':
                if i!=0 and res[i-1] != 'e' and res[i-1] != 'E':
                    return False
            else:
                return False

        return is_num

C++

class Solution {
public:
    bool isNumber(string s) {
        if (s.empty()) {
            return false;
        }

        // Trim leading and trailing whitespace
        s = trim(s);

        const char* res = s.c_str();
        int n = s.length();

        bool is_dot = false;
        bool is_e_or_E = false;
        bool is_num = false;
        for (int i = 0; i < n; i++) {
            if (res[i] >= '0' && res[i] <= '9') {
                is_num = true;
            } else if (res[i] == '.') {
                if (is_dot || is_e_or_E) {
                    return false;
                }
                is_dot = true;
            } else if (res[i] == 'e' || res[i] == 'E') {
                if (is_e_or_E || !is_num) {
                    return false;
                }
                is_e_or_E = true;
                is_num = false;
            } else if (res[i] == '-' || res[i] == '+') {
                if (i != 0 && res[i - 1] != 'e' && res[i - 1] != 'E') {
                    return false;
                }
            } else {
                return false;
            }
        }

        return is_num;
    }

private:
    string trim(const string& s) {
        string result = s;
        result.erase(result.begin(), find_if(result.begin(), result.end(), [](int ch) {
            return !isspace(ch);
        }));
        result.erase(find_if(result.rbegin(), result.rend(), [](int ch) {
            return !isspace(ch);
        }).base(), result.end());
        return result;
    }
};

Go

func isNumber(s string) bool {
    /*
    :type s: str
    :rtype: bool
    */
    // 有限状态机
    // 2.小数点 3.E/e 4.数字字符 5.-+
    if s == "" || len(s) <= 0 {
        return false
    }
    res := strings.TrimSpace(s)
    if len(res) <= 0 {
        return false
    }

    n := len(res)
    is_dot := false
    is_e_or_E := false
    is_num := false
    for i := 0; i < n; i++ {
        if res[i] >= '0' && res[i] <= '9' {
            is_num = true
        } else if res[i] == '.' {
            // -+ 8.  8.8  .8
            // 前面:不能有重复的小数点,也不能出现 e/E
            if is_dot || is_e_or_E {
                return false
            }
            is_dot = true
        } else if res[i] == 'e' || res[i] == 'E' {
            // 前面必须要有一个数字 || 前面不能出现重复的 e/E
            if is_e_or_E || !is_num {
                return false
            }
            is_e_or_E = true
            is_num = false //11E+ 11E
        } else if res[i] == '-' || res[i] == '+' {
            if i != 0 && res[i-1] != 'e' && res[i-1] != 'E' {
                return false
            }
        } else {
            return false
        }
    }

    return is_num
}

JS

/**
 * @param {string} s
 * @return {boolean}
 */
var isNumber = function(s) {
    // 有限状态机
    // 2. 小数点 3. E/e 4. 数字字符 5. -+
    if (s == null || s.length <= 0) {
        return false;
    }
    let res = s.trim().split('');
    if (res.length <= 0) {
        return false;
    }

    let n = res.length;
    let is_dot = false;
    let is_e_or_E = false;
    let is_num = false;
    for (let i = 0; i < n; i++) {
        if (res[i] >= '0' && res[i] <= '9') {
            is_num = true;
        } else if (res[i] === '.') {
            // -+ 8.  8.8  .8
            // 前面:不能有重复的小数点,也不能出现 e/E
            if (is_dot || is_e_or_E) {
                return false;
            }
            is_dot = true;
        } else if (res[i] === 'e' || res[i] === 'E') {
            // 前面必须要有一个数字 || 前面不能出现重复的 e/E
            if (is_e_or_E || !is_num) {
                return false;
            }
            is_e_or_E = true;
            is_num = false; // 11E+ 11E
        } else if (res[i] === '-' || res[i] === '+') {
            if (i !== 0 && res[i - 1] !== 'e' && res[i - 1] !== 'E') {
                return false;
            }
        } else {
            return false;
        }
    }

    return is_num;
};

发表回复

后才能评论