剑指 Offer 20. 表示数值的字符串(自动机状态转移)

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

题解:设计一个自动机状态转移算法,从一个起点状态开始,在不同状态下遇到数字、符号、e、E会产生状态转移,我们需要对转移后的状态进行状态检查,检查结果有两种,接受状态,则继续进行状态转移,直到字符串完全遍历;根据结束时状态的情况选择返回true或者false;拒绝状态,则直接返回false

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
class Solution {
    
    
    /*
    * 构造状态转移表:
    * 对于String[]的下标:
    * 0->表示当前位置是数,1->表示当前位置是".",2->表示当前位置是"e"或"E"
    * 3->表示当前位置是"-",4->表示当前位置是"+"
    * Int1:e之前的数的整数部分,Int2:e之后的数(不能是小数)
    * float1:e之前的数的小数部分
    * "+":数组最前面的“+”,"++":e后面的“+”(“-”同理)
    * "..":"+"或"-"后面的"."(表示整数部分省略的浮点数),".":表示正常浮点数的”.“
    * "e":表示数字中的“e”(科学计数法标识)
    * "end":表示状态拒绝
    */
    private  final static Map<String,String[]> map=new HashMap<String,String[]>(){
    
    
        {
    
    put("+",new String[]{
    
    "Int1","..","end","end","end"});
            put("++",new String[]{
    
    "Int2","end","end","end","end"});
            put("-",new String[]{
    
    "Int1","..","end","end","end"});
            put("--",new String[]{
    
    "Int2","end","end","end","end"});
            put(".",new String[]{
    
    "float1","end","e","end","end"});
            put("..",new String[]{
    
    "float1","end","end","end","end"});
            put("e",new String[]{
    
    "Int2","end","end","++","--"});
            put("Int1",new String[]{
    
    "Int1",".","e","end","end"});
            put("Int2",new String[]{
    
    "Int2","end","end","end","end"});
            put("float1",new String[]{
    
    "float1","end","e","end","end"});
        }};

    //进行状态转移的函数
    private  int conditionMove(char target){
    
    
        if(isDigit(target))
            return 0;
        else if(target=='.')
            return 1;
        else if(target=='e'||target=='E')
            return 2;
        else if(target=='+')
            return 3;
        else if(target=='-')
            return 4;
        else
            return -1;

    }
    private boolean isDigit(char arg){
    
    
        return arg-'0'>=0&&arg-'0'<=9;
    }
    //状态转移完成时,要检查当前的结束状态
    private boolean finish(String arg){
    
    
        String pattern1="Int.*";
        String pattern2="float.*";
        String pattern3="\\.";
        boolean a=Pattern.matches(pattern3,arg);
        return Pattern.matches(pattern1,arg)||Pattern.matches(pattern2,arg)||Pattern.matches(pattern3,arg);
    }

    public boolean isNumber(String s) {
    
    
        //去除字符串首尾的空格
        s=s.trim();
        //找到起始状态
        if(s.length()==0)
            return false;
        if(s.length()==1)
            return isDigit(s.charAt(0));
        String condition="";
        if(s.charAt(0)=='+')
            condition="+";
        else if(s.charAt(0)=='-')
            condition="-";
        else if(s.charAt(0)=='.')
            condition="..";
        else if(isDigit(s.charAt(0)))
            condition="Int1";
        else
            return false;

        for(int i=1;i<s.length();i++){
    
    
            char check=s.charAt(i);
            if(conditionMove(check)==-1)
                return false;
            condition=map.get(condition)[conditionMove(check)];
            if(condition.equals("end"))
                return false;
        }
        return finish(condition);
    }


}

时间复杂度:O(n)
空间复杂度:O(1)

猜你喜欢

转载自blog.csdn.net/CY2333333/article/details/108360295