字符串之表示数值的字符串

1.本题知识点

   字符串、有限状态自动机

2. 题目描述

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

3. 思路

   思路:首先,搞清楚组成数字的4个部分:
     ① 数字本身 0-9
     ② 数字符号 + 或 -
     ③ 小数点 .
     ④ e或E
   然后,判断每一个数字位.判断时需要考虑3种情况:
     ① 若是正负号,必须出现在首位或e的后一位
     ② 若是e,之前必须出现过数字且没出现过e
     ③ 若是.,之前必须没出现过.和e
   最后,需要设置4个标识位:
boolean pointSeen = false;//是否出现过小数点“.”
boolean eSeen =alse;//是否出现过指数标志“e”
boolean numberSeen = false;//是否出现过数字
boolean numberAfterE = true;//e后面是否有数字
   注意:字符串和模式串是每个字符依次比较的。而且要弄懂 . 和 * 的意思。

4 具体实现:

   4.1 if else实现,简单粗暴,枚举所有情况:
/**
     * if else 实现
     * 
     * 思路:首先,搞清楚组成数字的4个部分:
       			1.数字本身 0-9
				2.数字符号 + 或 -
				3.小数点  .
				4.e或E
				
			 然后,判断每一个数字位.判断时需要考虑3种情况:
			 	1.若是正负号,必须出现在首位或e的后一位
			 	2.若是e,之前必须出现过数字且没出现过e
			 	3.若是.,之前必须没出现过.和e
			 	
			 最后,需要设置4个标识位:
     * 			boolean pointSeen = false;//是否出现过小数点“.”
     * 			boolean eSeen =alse;//是否出现过指数标志“e”
     * 			boolean numberSeen = false;//是否出现过数字
     * 			boolean numberAfterE = true;//e后面是否有数字
     * @param s
     * @return
     */
    public static boolean isNumeric2(char[] s) {
        if (s == null || s.length == 0)
            return false;
        // 记录是否出现过数字
        boolean numberSeen = false;
        // 是否出现过小数点
        boolean pointSeen = false;
        // 是否出现过指数标志e
        boolean eSeen = false;
        // e后是否出现过数字
        boolean numberAfterE = false;
 
        for (int i = 0; i < s.length; i++) {
            char c = s[i];
            // 如果是数字
            if (c >= '0' && c <= '9') {
                numberSeen = true;
                numberAfterE = true;//对于输入为纯数字的情况,要先设为true
                // 如果是小数点
            } else if (c == '.') {
                if (pointSeen || eSeen)
                    return false;
                pointSeen = true;
                // 如果是e || E,必须没有出现过且出现过数字
            } else if (c == 'e' || c == 'E') {
                if (eSeen || !numberSeen)
                    return false;
                eSeen = true;
                numberAfterE = false;
                // 如果出现正负号,必须是首位,或者前一位是e || E
            } else if (c == '+' || c == '-') {
                if (i != 0 && s[i - 1] != 'e' && s[i - 1] != 'E')
                    return false;
            } else
                return false;
        }
        return numberSeen && numberAfterE;
    }






   4.2 有限状态机实现,理解复杂:

字符串之表示数值的字符串_第1张图片

   从图中我们发现,只有1、4、7、8四种状态是合法的。
package com.algorithm.str;

/**
 * 自动机实现表示数值的字符串 组成部分:空格、符号、数字、点、指数
 * 
 * @author wxq
 *
 */
public class AC2 {
	
	enum InputType {
		START,     // 0
		SPACE,     // 1
		SIGN,      // 2
		DIGIT,     // 3
		DOT,       // 4
		EXPONENT   // 5
//		NUM_INPUTS // 6
	};
	
	//定义状态迁移表, 不画图理解有点困难
	//状态迁移表矩阵:每一行为当前状态的下一状态的多种取值
	private static int transitionTable[][] ={
	  //start SPACE SIGN DIGIT DOT  E
         {-1,   0,   3,   1,   2,  -1},     // next states for state 0 
         {-1,   8,  -1,   1,   4,   5},     // next states for state 1
         {-1,  -1,  -1,   4,  -1,  -1},     // next states for state 2
         {-1,  -1,  -1,   1,   2,  -1},     // next states for state 3
         {-1,   8,  -1,   4,  -1,   5},     // next states for state 4
         {-1,  -1,   6,   7,  -1,  -1},     // next states for state 5
         {-1,  -1,  -1,   7,  -1,  -1},     // next states for state 6
         {-1,   8,  -1,   7,  -1,  -1},     // next states for state 7
         {-1,   8,  -1,  -1,  -1,  -1},     // next states for state 8
     };

	/**
	 * 有限状态自动机实现
	 * 
	 * @param string
	 * @return
	 */
	static boolean isNumeric(char[] string) {
		int state = 0;
		for(int i = 0; i < string.length; i++){
			char c = string[i];
			InputType inputType = InputType.START;//设置初始值
			
			//如果输入字符为空格
			if(" ".equals(c)){
				inputType = InputType.SPACE;
			}
			//如果输入字符为+-号
			else if(c == '+' || c == '-'){
				inputType = InputType.SIGN;
			}
			//如果输入字符为数字
			else if(c >= '0' && c <= '9'){
				inputType = InputType.DIGIT;
			}
			//如果输入字符为点
			else if(c == '.'){
				inputType = InputType.DOT;
			}
			//如果输入字符为e E
			else if(c == 'e' || c == 'E'){
				inputType = InputType.EXPONENT;
			}
			
			state = transitionTable[state][inputType.ordinal()];
			
			if (state == -1) return false;
		}
		
		return state == 1 || state == 4 || state == 7 || state == 8;
	}

	public static void main(String[] args) throws InterruptedException {
//		String num = "-1e-16";
		 String num = ".8";
		// long start = System.currentTimeMillis();
		// Thread.sleep(1);
		System.out.println(isNumeric(num.toCharArray()));
		// System.out.println("执行时长:"+(System.currentTimeMillis() -
		// start)+" ms");
	}

}

参考 - 1
参考 - 2
参考 - 3
参考 - 4

你可能感兴趣的:(数据结构和算法)