题面

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"-1E-16"、"0123"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"及"12e+5.4"都不是。

原题链接

分析

除非接受过专业训练,否则一开始很难想到用自动机(Automata)来做,我是一开始凭直觉列举出不同的规则,然后不断的用测试用例试错,最终通过所有测试用例。

下面的代码没有任何参考意义,注释部分可以看一看。

做完本题最大的意义在于:

  1. 理解官方自动机解法的优越性
  2. 巩固了一些C++基础语法知识

源代码(注释部分即为思路)

class Solution {
public:
    bool isNumber(string s) {
        char candidate[15] = {'0','1','2','3','4','5','6','7','8','9','.','+','-','E','e'};
        set<char> cand;
        for(int i=0; i<15; i++){
            cand.insert(candidate[i]);
        }
        set<char> cand2;
        for(int i=0; i<10; i++){
            cand2.insert(candidate[i]);
        }
        
        //cand3没有存在的必要性
        set<char> cand3;
        for(int i=0; i<13; i++){
            cand3.insert(candidate[i]);
        }

        
        int rawLen = s.length();
        for(int i=0; i<rawLen; i++){
            
            if(s[i]==' '){
                int tmpL = i;
                int tmpR = i;
                //防止空格有多个
                while(s[tmpL]==' ' && tmpL>0){
                    tmpL--;
                }
                while(s[tmpR]==' ' && tmpR<rawLen-1){
                    tmpR++;
                }
                
                if(cand.find(s[tmpL])!=cand.end() &&  cand.find(s[tmpR])!=cand.end()){
                    return false;
                }
            }
        }


        
        //之前是判断和空格有关的情况
        //删除掉所有的空格
        s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
        //之后是去掉所有空格之后进行判断

        int len = s.length();
    
        //特判
        if(len==0){
            return false;
        }
        //特判
        if(len==1){
            if(s[0]=='+' || s[0]=='-' || s[0]=='.' || s[0]=='E' || s[0]=='e'){
                return false;
            }
            else{
                if(cand.find(s[0])!=cand.end()){
                    return true;
                }
                else{
                    return false;
                }
            }
        }
        //特判
        if(s[1]=='+' || s[1]=='-' || s[len-1]=='e' || s[len-1] == 'E'){
            return false;
        }
        /*后两个特判意义不大*/
        
        
        
        int dotNumber = 0;
        int eNumber = 0;


        int dotPosition = -1;
        int ePosition = -1;


        for(int i=0; i<len; i++){
            if(cand.find(s[i])==cand.end()){
                return false;
            }
            else{
                if(s[i]=='.'){
                    //.最多只能出现一次
                    dotNumber++;
                    dotPosition = i;
                    if(dotNumber>=2){
                        return false;
                    }
                    if(dotPosition==len-1){
                        if(cand2.find(s[dotPosition-1])==cand2.end()){
                            return false;
                        }
                    }
                    // cout<<dotPosition;
                }
                if(s[i] == 'e' || s[i]=='E'){
                    eNumber++;
                    ePosition = i;
                    if(eNumber>=2){
                        return false;
                    }
                }
                if(s[i]=='+' || s[i]=='-'){
                    if(ePosition==-1){
                        if(i!=0){
                            return false;
                        }
                    }
                    else{
                        if(i!=0){
                            if(i!=ePosition+1){
                                return false;
                            }
                        }
                    }
                }

            }
        }
        //e之后不能再有小数点
        if(ePosition !=-1 && dotPosition !=-1 && ePosition<dotPosition){
            return false;
        }
        
        if(ePosition!=-1){
            //e前面的那一个字符,必须是数字或者‘.'
            if((ePosition-1)<0 || s[ePosition-1]=='+' || s[ePosition-1]=='-'){
                return false;
            }
            else{
                //如果e前面那一个字符是.
                if(s[ePosition-1]=='.'){
                    if((ePosition-2)<0 || cand2.find(s[ePosition-2])==cand2.end()){
                        return false;
                    }
                }
            }
            
            if(s[ePosition+1]=='+' || s[ePosition+1]=='-'){
                if(ePosition+2>=len){
                    return false;
                }
                for(int k=ePosition+2; k<len; k++){
                    if(cand2.find(s[k])==cand2.end()){
                        return false;
                    }
                }
            }
            //e后面第一位出现的不是加号和减号
            else{
                if(ePosition+1>=len){
                    return false;
                }
                for(int k=ePosition+1; k<len; k++){
                    if(cand2.find(s[k])==cand2.end()){
                        return false;
                    }
                }
            }
            
        }
        return true;
    }
};

提交结果:

image

官方题解

image

原文链接

C++语法知识巩固

  • set类型中,元素可以是char类型
  • char数组的赋值方法:

    char candidate[15] = {'0','1','2','3','4','5','6','7','8','9','.','+','-','E','e'};
    //注意,赋值号右边是大括号
    
    char candidate[6] = "Hello";
    //注意,字符串后面自带一个\0,所以char数组的长度要比字符串视觉长度大1

    实验演示:

    #include <iostream>
    #include <string.h>
    using namespace std;
    
    int main()
    {
        char candidate[6] = "Hello";
        cout<<candidate<<endl;
        cout<<sizeof(candidate)<<endl;
        //strlen函数包含在string.h头文件里
        //string.h头文件包含C语言中的字符串处理函数,如strlen,strcmp等等
        //string头文件包含C++中的STL模板string
        cout<<strlen(candidate)<<endl;
        return 0;
    }

    image

  • 判断某个元素是否在set类型中:

    set<typename> now;
    if(now.find(element)==now.end()){
        //element元素不在now集合中
        cout<<"element元素不在now集合中";
    }
  • C++中去除字符串s中的所有空格:

    s.erase(std::remove(s.begin(), s.end(), ' '), s.end());

Alan
0 声望0 粉丝