Leetcode剑指offer(三)

19、表示数值的字符串(20、Medium)

1)题目要求

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

2)我的解法

1、利用正则表达式

class Solution {
    public boolean isNumber(String s) {
        String s1=s.trim();
        return s1.matches("(\\+|\\-)?((\\d+)|(\\d+\\.\\d*)|(\\d*\\.\\d+))((E|e)(\\+|\\-)?\\d+)?");
    }
}

2、一点一点试出来的,太恶心了

在这里插入图片描述

class Solution {
    public boolean isNumber(String s) {
        String s1=s.trim();
        int i=0;
        if(s1.length()==0)return false;
        if(s1.charAt(0)=='+'||s1.charAt(0)=='-')i++;
        while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
            i++;
        }
        if(i<s1.length()&&s1.charAt(i)=='.'){
            i++;
            while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
                i++;
            }
            if(s1.charAt(i-1)=='.'&&(i<2||s1.charAt(i-2)=='+'||s1.charAt(i-2)=='-'))return false;
        }
        if(i>0&&s1.charAt(i-1)!='+'&&s1.charAt(i-1)!='-'&&i<s1.length()&&(s1.charAt(i)=='e'||s1.charAt(i)=='E')){
            i++;
            if(i<s1.length()&&(s1.charAt(i)=='+'||s1.charAt(i)=='-'))i++;
            while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
                i++;
            }
        }
        if(i==s1.length()&&s1.charAt(s1.length()-1)!='E'&&s1.charAt(s1.length()-1)!='e'
        &&s1.charAt(s1.length()-1)!='+'&&s1.charAt(s1.length()-1)!='-')return true;
        else return false;

    }
}

3)其他解法

1、

在这里插入图片描述

在这里插入图片描述

(可以在2、3之间加一个小数点状态,便于理解)

在这里插入图片描述

class Solution {
    public boolean isNumber(String s) {
        Map[] states = {//理解为邻接矩阵
            new HashMap<>() {{ put(' ', 0); put('s', 1); put('d', 2); put('.', 4); }}, // 0.
            new HashMap<>() {{ put('d', 2); put('.', 4); }},                           // 1.
            new HashMap<>() {{ put('d', 2); put('.', 3); put('e', 5); put(' ', 8); }}, // 2.
            new HashMap<>() {{ put('d', 3); put('e', 5); put(' ', 8); }},              // 3.
            new HashMap<>() {{ put('d', 3); }},                                        // 4.
            new HashMap<>() {{ put('s', 6); put('d', 7); }},                           // 5.
            new HashMap<>() {{ put('d', 7); }},                                        // 6.
            new HashMap<>() {{ put('d', 7); put(' ', 8); }},                           // 7.
            new HashMap<>() {{ put(' ', 8); }}                                         // 8.
        };
        int p = 0;
        char t;
        for(char c : s.toCharArray()) {
            if(c >= '0' && c <= '9') t = 'd';
            else if(c == '+' || c == '-') t = 's';
            else if(c == 'e' || c == 'E') t = 'e';
            else if(c == '.' || c == ' ') t = c;
            else t = '?';
            if(!states[p].containsKey(t)) return false;
            p = (int)states[p].get(t);
        }
        return p == 2 || p == 3 || p == 7 || p == 8;
    }
}

作者:jyd
链接:link
来源:力扣(LeetCode)

2、

class Solution {
    public boolean isNumber(String s) {
        if(s == null || s.length() == 0){
            return false;
        }
        //标记是否遇到相应情况
        boolean numSeen = false;
        boolean dotSeen = false;
        boolean eSeen = false;
        char[] str = s.trim().toCharArray();
        for(int i = 0;i < str.length; i++){
            if(str[i] >= '0' && str[i] <= '9'){
                numSeen = true;
            }else if(str[i] == '.'){
                //.之前不能出现.或者e
                if(dotSeen || eSeen){
                    return false;
                }
                dotSeen = true;
            }else if(str[i] == 'e' || str[i] == 'E'){
                //e之前不能出现e,必须出现数
                if(eSeen || !numSeen){
                    return false;
                }
                eSeen = true;
                numSeen = false;//重置numSeen,排除123e或者123e+的情况,确保e之后也出现数
            }else if(str[i] == '-' || str[i] == '+'){
                //+-出现在0位置或者e/E的后面第一个位置才是合法的
                if(i != 0 && str[i-1] != 'e' && str[i-1] != 'E'){
                    return false;
                }
            }else{//其他不合法字符
                return false;
            }
        }
        return numSeen;
    }
}

作者:yangshyu6
链接: link
来源:力扣(LeetCode)

4)自己的优化代码

1、

class Solution {
    public boolean isNumber(String s) {
        String s1=s.trim();
        int i=0;
        if(s1.length()==0)return false;
        if(s1.charAt(0)=='+'||s1.charAt(0)=='-')i++;//正负号
        while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){//数字
            i++;
        }
        if(i<s1.length()&&s1.charAt(i)=='.'){//小数点
            i++;
            while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
                i++;//小数数字
            }
            //若小数点前后均无数字则返回false
            if(s1.charAt(i-1)=='.'&&(i<2||s1.charAt(i-2)=='+'||s1.charAt(i-2)=='-'))return false;
        }
        if(i>0&&s1.charAt(i-1)!='+'&&s1.charAt(i-1)!='-'&&i<s1.length()&&(s1.charAt(i)=='e'||s1.charAt(i)=='E')){//e|E
            i++;
            正负号
            if(i<s1.length()&&(s1.charAt(i)=='+'||s1.charAt(i)=='-'))i++;
            while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
                i++;//数字
            }
        }
        if(i==s1.length()&&s1.charAt(s1.length()-1)!='E'&&s1.charAt(s1.length()-1)!='e'
        &&s1.charAt(s1.length()-1)!='+'&&s1.charAt(s1.length()-1)!='-')return true;
        else return false;
        //return s1.matches("(\\+|\\-)?((\\d+)|(\\d+\\.\\d*)|(\\d*\\.\\d+))((E|e)(\\+|\\-)?\\d+)?");
    }
}

2、有穷自动机

在这里插入图片描述

class Solution {
    public boolean isNumber(String s) {
        Map[] state=new Map[]{//相当于邻接表
            new HashMap() {{ put(' ', 0); put('s', 1); put('d', 2); put('.', 4); }}, 
            new HashMap() {{ put('d', 2); put('.', 4); }},                          
            new HashMap() {{ put('d', 2); put('.', 3); put('e', 5); put(' ', 8); }}, 
            new HashMap() {{ put('d', 3); put('e', 5); put(' ', 8); }},              
            new HashMap() {{ put('d', 3); }},                                       
            new HashMap() {{ put('s', 6); put('d', 7); }},                         
            new HashMap() {{ put('d', 7); }},                                       
            new HashMap() {{ put('d', 7); put(' ', 8); }},                         
            new HashMap() {{ put(' ', 8); }}         
        };
        char zt;
        int p=0;
        for(char c:s.toCharArray()){
            if(c>='0'&&c<='9')zt='d';
            else if(c=='+'||c=='-')zt='s';
            else if(c=='e'||c=='E')zt='e';
            else if(c=='.')zt='.';
            else if(c==' ')zt=' ';
            else return false;

            if(!state[p].containsKey(zt))return false;
            p=(int)state[p].get(zt);
        }
        return p==2||p==3||p==7||p==8;
    }
}

5)学到的东西

正则表达式

在这里插入图片描述

在这里插入图片描述

Map数组,不能加尖括号

HashMap直接初始化:(两个大括号)
new HashMap() {{ put(’ ‘, 0); put(‘s’, 1); put(‘d’, 2); put(’.’, 4); }}

有穷自动机

考虑所有的状态,再把每一个状态的转换关系画出来(一个个画,别着急),再确定合法的结束状态

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值