剑指offer20 表示数值的字符串

146 阅读2分钟

题目

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

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

  1. 若干空格
  2. 一个 小数 或者 整数
  3. (可选)一个 'e' 或 'E' ,后面跟着一个整数
  4. 若干空格
    小数(按顺序)可以分成以下几个部分:
  5. (可选)一个符号字符('+' 或 '-')
  6. 下述格式之一:
    1. 至少一位数字,后面跟着一个点 '.'
    2. 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
    3. 一个点 '.' ,后面跟着至少一位数字 整数(按顺序)可以分成以下几个部分:
  7. (可选)一个符号字符('+' 或 '-')
  8. 至少一位数字 部分数值列举如下:
  • ["+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),加号 '+' ,减号 '-' ,空格 ' ' 或者点 '.' 。

思路

第一个是多重的if-else判断,比较繁琐,一个一个条件写下来,慢慢调整,考验人分情况的能力:

class Solution {
public:
    bool isNumber(string s) {
        //删除前后空格
        int i = 0;
        while (i < s.size() && s[i] == ' ') i ++ ;
        int j = s.size() - 1;
        while (j >= 0 && s[j] == ' ') j -- ;
        if (i > j) return false;
        s = s.substr(i, j - i + 1);

        //删除整数前面的符号,并判断是否满足条件
        if (s[0] == '-' || s[0] == '+') s = s.substr(1);
        if (s.empty() || s[0] == '.' && s.size() == 1) return false;

        int dot = 0, e = 0;//dot是小数点的数量 e是e或者E的数量,都只能为1
        for (int i = 0; i < s.size(); i ++ ) {
            if (s[i] >= '0' && s[i] <= '9');//数字前进一位
            else if (s[i] == '.') {
                dot ++ ;
                if (e || dot > 1) return false;
            }
            else if (s[i] == 'e' || s[i] == 'E'){
                e ++ ;
                if (i + 1 == s.size() || !i || e > 1 || (i == 1 && s[0] == '.')) return false;
                //注意e后面必须有整数,可以有符号,后面也必须有整数
                //!i表示前面没有数字或小数点(字符)
                //i + 1 == s.size()表示后面没有数字
                //i == 1 && s[0] == '.' 表示e前面只有一个小数点,可以与!i一起排除前面掉没有整数的情况
                if (s[i + 1] == '+' || s[i + 1] == '-'){
                    //e后面的东西,如果后面没有了就报错,不然就前进一位
                    if (i + 2 == s.size()) return false;
                    i ++ ;
                }
            }
            else return false;//无法识别fslae
        }
        return true;
    }
};

还有是剑指对本题的题解,比较精简

class Solution {
public:

    bool isSgin(string &s,int &index){
        if(s[index] == '+' || s[index] == '-') index++;//满足是符号,前进一位

        return isInteger(s,index);//判断是否是整数
    }

    bool isInteger(string &s,int &index){
        int temp = index;
        while(s[index] <= '9' && s[index] >= '0' && index < s.size()) index++;
        return index > temp;//返回是否整数
    }

    bool isNumber(string s) {
        //if(s.size() == 0) return false;
        int index = 0;//遍历字符串的位置
        while(s[index] == ' ') index++;
            
        bool isPrime = isSgin(s,index);//isPrime用作判断

        if(s[index] == '.') {
            index++;//检查是否是有小数点

            isPrime = isInteger(s,index) || isPrime;//再判断小数点后面是否整数
        }
        
        if(s[index] == 'e' || s[index] == 'E') {
            index++;

            isPrime = isSgin(s,index) && isPrime;//再判断e后
        }
        while(s[index] == ' ') index++;

        return isPrime && s.size() == index;
    }
};