剑指offer20题表示数值的字符串:这题实在是太优雅了


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

    这个题目有官方解释的有限状态自动机,也有用正则肝的,甚至有暴躁老哥打算直接把这题撕了的,但是,还得是评论区里人才多,总有大佬能肝出来清晰的题解,这波记录一下,食用这个题目的过程。
    在这里插入图片描述
    大佬讲解链接:https://www.bilibili.com/video/BV1KP411L7VH/?p=20&vd_source=a3808e6f1547cd8a5765ed7361e92529

    一、憨憨初解

    1、思路

    看完题目感觉没什么难的,字符串处理题么应该是,从字符串开始到最后遍历就完事儿,用cur记录遍历的长度,如果最后能够按照题目给的规则遍历完,那么cur就等于字符串的长度就返回true,否则false

    2、代码

    class Solution {
    public:
        bool isNumber(string s) {
            if (s.empty() || s.size() == 0) return false;
            int cur=0;
            while(s[cur] == ' ')  cur++;//去调首部空格
            //处理一个整数或者小数
            if(s[cur] == '+' || s[cur] == '-') cur++;
            while(s[cur] >= '0' && s[cur] <= '9')    cur++;
            if(s[cur] == '.') cur++;
            while(s[cur] >= '0' && s[cur] <= '9')    cur++;
    
            //处理e和E以及一个整数
            if(s[cur]=='e' || s[cur]=='E') cur++;
            if(s[cur] == '+' || s[cur] == '-') cur++;
            while(s[cur] >= '0' && s[cur] <= '9')    cur++;
    
            while(s[cur] == ' ')  cur++;//处理尾部空格
            return cur==s.size();
        }
    };
    

    3、战绩

    在这里插入图片描述

    4、反思

    存在一些情况没有考虑,憨憨我直接一波下去了,看题解看的有点懵,然后看大佬视频题解后,理解了思路,自己用C++复现了一波;

    二、看懂再解

    1、思路

    首先判断为空字符串的返回false,然后用trim去除段首段尾空格;
    定义三个标准布尔量,分别表示数字和点还要e或者E是否出现过,从开始到结尾进行遍历,如果出现了不符合标准的情况就返回false。

    这个不符合标准的情况规律是大佬以身探出来的,感恩一下前人,自己很难严谨的考虑到这些东西。

    1、小数点出现的时候,前面不能出现过小数点或者是出现过e;

    • 解释:'.'只能在底数上,不能在指数上,且只能出现一次,'.'两边任一边有数字均算一个完整的数字,但单独一个'.'不行。

    2、e或者E出现的时候,前面不能出现过eE,并且必须出现过一个数字;

    • 解释:e、E用来划分底数与指数,只能出现一次,前面为科学计数法的底数,后面为指数;

    3、+-符号,只能出现在第一位或者紧接e后面;

    • 解释:'+'、'-'只能作为正负号出现在底数和指数的前面,不能出现在两个数字中间;

    特别需要注意的是为了避免123e这种请求,出现e之后就标志is_num为false,最后返回is_num即可!
    其实不用看解释,理解即可,记好这三条规律和一个特别的情况就能快速的编写出解题代码!

    2、代码

    复现的C++版:

    class Solution {
    public:
        static void trim(string &s){
            if( !s.empty() ){
                s.erase(0,s.find_first_not_of(" "));
                s.erase(s.find_last_not_of(" ") + 1);
            }
        }
        bool isNumber(string s) {
            if (s.empty() || s.size() == 0) return false;
            trim(s);
            bool is_num = false;//判断数字是否出现过
            bool is_dot = false;//判断.是否出现过
            bool is_eorE = false;//判断e或者E是否出现过
            int i = 0,size = s.size();
            for (; i < size; i++) {
                //判定为数字,则标记is_num
                if (s[i] >= '0' && s[i] <= '9') {   
                    is_num = true;
                //判定为.  需要前面没出现过.并且没出现过e
                } else if (s[i] == '.' && !is_dot && !is_eorE) {  
                    is_dot = true;       
                //判定为e或者E,需要前面没出现过e,并且出现过数字
                } else if ((s[i]=='e' || s[i]=='E') && !is_eorE && is_num) {
                    is_eorE = true;
                    is_num = false;//为了避免123e这种请求,出现e之后就标志为false      
                //判定为+-符号,只能出现在第一位或者紧接e后面
                } else if (s[i] == '-' || s[i] == '+'){
                    if(i!=0 && s[i-1] != 'e' && s[i-1] != 'E'){
                        return false;
                    }
                } else {
                    return false;
                }
            }
            return is_num;
        }
    };
    

    大佬的Java版:

    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;
        }
    }
    
    

    3、C++版战绩

    在这里插入图片描述

    总结

    高情商:考察编程代码严谨能力!
    低情商:不太想要你。

    开玩笑的蛤,不要太当真,不管什么问题,都要能够具备解决它的能力,这题虽然比较难受,但是还是学到了一点东西的。
    发现了一个宝藏博主:https://www.cnblogs.com/Shirlies/p/4666744.html
    大佬题解页面:https://www.playoffer.cn/84.html