6

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

 1 year ago
source link: https://www.cnblogs.com/binbincome/p/16858714.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

这个题目有官方解释的有限状态自动机,也有用正则肝的,甚至有暴躁老哥打算直接把这题撕了的,但是,还得是评论区里人才多,总有大佬能肝出来清晰的题解,这波记录一下,食用这个题目的过程。

在这里插入图片描述

大佬讲解链接:https://www.bilibili.com/video/BV1KP411L7VH/?p=20&vd_source=a3808e6f1547cd8a5765ed7361e92529

一、憨憨初解

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

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();
    }
};
在这里插入图片描述

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

二、看懂再解

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

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

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

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

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

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

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

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

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

复现的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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK