劍指offer20題表示數值的字串:這題實在是太優雅了

2022-11-04 21:01:00

前言

題目來源: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