剑指 Offer 20. 表示数值的字符串

题目:

思路:

【1】感觉常规思路比状态机要好理解,但是状态机怎么说,面试又需要真他妈忧愁

代码展示:

常规的思路解法:

//时间1 ms击败100%
//内存41.5 MB击败55.87%
class Solution {
    public boolean isNumber(String s) {
        // 字符数组
        char[] charArray = s.toCharArray();
        // 字符串长度
        int n = charArray.length;

        // 当前下标
        int index = 0;

        // 标记
        boolean hasNum = false, hasE = false;
        boolean hasSign = false, hasDot = false;

        // 将下标移动到非空格字符上
        while (index < n && charArray[index] == ' ') {
            index++;
        }

        // 当前下标尚未到达字符串末尾
        while (index < n) {
            // 当前字符
            char c = charArray[index];

            if (c >= '0' && c <= '9') {
                // 当前字符是数字 0~9
                hasNum = true;
            } else if (c == 'e' || c == 'E') {
                // 当前字符是 e / E
                if (hasE || !hasNum) {
                    // e / E 已经出现过,或者数字没有出现过,则该字符串必定无法表示数值,返回 false
                    return false;
                }
                hasE = true;
                hasNum = false;
                hasSign = false;
                hasDot = false;
            } else if (c == '+' || c == '-') {
                // 当前字符是正负号
                if (hasSign || hasNum || hasDot) {
                    // 如果已经出现过符号、数字、小数点,则该字符串必定无法表示数值,返回 false
                    return false;
                }
                hasSign = true;
            } else if (c == '.') {
                // 如果是小数点
                if (hasDot || hasE) {
                    // 如果已经出现过小数点、e / E ,则该字符串必定无法表示数值,返回 false
                    return false;
                }
                hasDot = true;
            } else if (c == ' ') {
                // 如果是空格,跳出循环
                break;
            } else {
                // 非法字符
                return false;
            }

            // 继续判断下一个字符
            index++;
        }

        // 如果当前下标尚未到达字符串末尾,则剩下的字符应当全部为空格,否则该字符串必定无法表示数值,返回 false
        for (; index < n; index++) {
            if (charArray[index] != ' ') {
                return false;
            }
        }

        return hasNum;
    }
}

 

官方的状态机解法:

//时间5 ms击败25.31%
//内存41.5 MB击败55.30%
class Solution {
    public boolean isNumber(String s) {
        Map<State, Map<CharType, State>> transfer = new HashMap<State, Map<CharType, State>>();
        Map<CharType, State> initialMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_SPACE, State.STATE_INITIAL);
            put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
            put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
            put(CharType.CHAR_SIGN, State.STATE_INT_SIGN);
        }};
        transfer.put(State.STATE_INITIAL, initialMap);
        Map<CharType, State> intSignMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
            put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
        }};
        transfer.put(State.STATE_INT_SIGN, intSignMap);
        Map<CharType, State> integerMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
            put(CharType.CHAR_EXP, State.STATE_EXP);
            put(CharType.CHAR_POINT, State.STATE_POINT);
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_INTEGER, integerMap);
        Map<CharType, State> pointMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
            put(CharType.CHAR_EXP, State.STATE_EXP);
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_POINT, pointMap);
        Map<CharType, State> pointWithoutIntMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
        }};
        transfer.put(State.STATE_POINT_WITHOUT_INT, pointWithoutIntMap);
        Map<CharType, State> fractionMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
            put(CharType.CHAR_EXP, State.STATE_EXP);
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_FRACTION, fractionMap);
        Map<CharType, State> expMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
            put(CharType.CHAR_SIGN, State.STATE_EXP_SIGN);
        }};
        transfer.put(State.STATE_EXP, expMap);
        Map<CharType, State> expSignMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
        }};
        transfer.put(State.STATE_EXP_SIGN, expSignMap);
        Map<CharType, State> expNumberMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_EXP_NUMBER, expNumberMap);
        Map<CharType, State> endMap = new HashMap<CharType, State>() {{
            put(CharType.CHAR_SPACE, State.STATE_END);
        }};
        transfer.put(State.STATE_END, endMap);

        int length = s.length();
        State state = State.STATE_INITIAL;

        for (int i = 0; i < length; i++) {
            CharType type = toCharType(s.charAt(i));
            if (!transfer.get(state).containsKey(type)) {
                return false;
            } else {
                state = transfer.get(state).get(type);
            }
        }
        return state == State.STATE_INTEGER || state == State.STATE_POINT || state == State.STATE_FRACTION || state == State.STATE_EXP_NUMBER || state == State.STATE_END;
    }

    public CharType toCharType(char ch) {
        if (ch >= '0' && ch <= '9') {
            return CharType.CHAR_NUMBER;
        } else if (ch == 'e' || ch == 'E') {
            return CharType.CHAR_EXP;
        } else if (ch == '.') {
            return CharType.CHAR_POINT;
        } else if (ch == '+' || ch == '-') {
            return CharType.CHAR_SIGN;
        } else if (ch == ' ') {
            return CharType.CHAR_SPACE;
        } else {
            return CharType.CHAR_ILLEGAL;
        }
    }

    enum State {
        STATE_INITIAL,
        STATE_INT_SIGN,
        STATE_INTEGER,
        STATE_POINT,
        STATE_POINT_WITHOUT_INT,
        STATE_FRACTION,
        STATE_EXP,
        STATE_EXP_SIGN,
        STATE_EXP_NUMBER,
        STATE_END
    }

    enum CharType {
        CHAR_NUMBER,
        CHAR_EXP,
        CHAR_POINT,
        CHAR_SIGN,
        CHAR_SPACE,
        CHAR_ILLEGAL
    }
    
}

 

posted @ 2023-02-01 16:22  忧愁的chafry  阅读(22)  评论(0)    收藏  举报