LeetCode 65. Valid Number(校验数字)

原题网址:https://leetcode.com/problems/valid-number/

Validate if a given string is numeric.

Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true

Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.

Update (2015-02-10):
The signature of the C++ function had been updated. If you still see your function signature accepts a const char * argument, please click the reload button  to reset your code definition.

思路:使用有限状态自动机。


方法一:使用完整的有限状态自动机。

public class Solution {
    private int accept = 9;
    private NFA nfa = new NFA();
    {
        nfa.put(0, null, 1);
        nfa.put(1, ' ', 1);
        nfa.put(1, '+', 2);
        nfa.put(1, '-', 2);
        nfa.put(1, null, 2);
        for(char ch='0'; ch<='9'; ch++) nfa.put(2, ch, 3);
        for(char ch='0'; ch<='9'; ch++) nfa.put(3, ch, 3);
        nfa.put(3, '.', 4);
        for(char ch='0'; ch<='9'; ch++) nfa.put(4, ch, 4);
        nfa.put(4, null, 5);
        nfa.put(3, null, 5);
        nfa.put(2, '.', 10);
        for(char ch='0'; ch<='9'; ch++) nfa.put(10, ch, 11);
        for(char ch='0'; ch<='9'; ch++) nfa.put(11, ch, 11);
        nfa.put(11, null, 5);
        nfa.put(5, 'e', 6);
        nfa.put(5, 'E', 6);
        nfa.put(6, '+', 7);
        nfa.put(6, '-', 7);
        nfa.put(6, null, 7);
        for(char ch='0'; ch<='9'; ch++) nfa.put(7, ch, 8);
        for(char ch='0'; ch<='9'; ch++) nfa.put(8, ch, 8);
        nfa.put(8, null, 9);
        nfa.put(5, null, 9);
        nfa.put(9, ' ', 9);
    }
    public boolean isNumber(String s) {
        Set<Integer> states = new HashSet<>();
        states.add(0);
        states = nfa.getClosure(states);
        for(int i=0; i<s.length(); i++) {
            Set<Integer> nexts = new HashSet<>();
            for(Integer state: states) {
                nexts.addAll(nfa.get(state, s.charAt(i)));
            }
            states = nfa.getClosure(nexts);
            // System.out.printf("[%d]%c, states=%s\n", i, s.charAt(i), states);
        }
        return states.contains(accept);
    }
}

class NFA {
    public Map<Integer, Map<Character, List<Integer>>> transitions = new HashMap<>();
    Set<Integer> getClosure(Set<Integer> states) {
        Set<Integer> closure = new HashSet<>();
        closure.addAll(states);
        Set<Integer> found = new HashSet<>();
        found.addAll(states);
        while (!found.isEmpty()) {
            Set<Integer> epsilons = new HashSet<>();
            for(Integer state: found) {
                List<Integer> epsilon = transitions.get(state).get(null);
                if (epsilon != null ) {
                    closure.addAll(epsilon);
                    epsilons.addAll(epsilon);
                }
            }
            found = epsilons;
        }
        return closure;
    }
    public void put(int state, Character ch, int next) {
        Map<Character, List<Integer>> transition = transitions.get(state);
        if (transition == null) {
            transition = new HashMap<Character, List<Integer>>();
            transitions.put(state, transition);
        }
        List<Integer> nexts = transition.get(ch);
        if (nexts == null) {
            nexts = new ArrayList<>();
            transition.put(ch, nexts);
        }
        nexts.add(next);
    }
    Set<Integer> get(int state, char ch) {
        Map<Character, List<Integer>> transition = transitions.get(state);
        if (transition == null) return new HashSet<>();;
        List<Integer> nexts = transition.get(ch);
        if (nexts == null) return new HashSet<>();
        return new HashSet<>(nexts);
    }
}

方法二:使用简化的状态机。


public class Solution {
    public boolean isNumber(String s) {
        char[] sa = s.toCharArray();
        int state = 0;
        for(int i=0; i<sa.length; i++) {
            switch (state) {
            case 0:
                if (sa[i] == ' ') continue;
                if (sa[i] == '+' || sa[i] == '-') { state = 1; continue; }
                if (sa[i] >= '0' && sa[i] <= '9') { state = 2; continue; }
                if (sa[i] == '.') { state = 3; continue; }
                return false;
            case 1:
                if (sa[i] == '.') { state = 3; continue; }
                if (sa[i] >= '0' && sa[i] <= '9') { state = 2; continue; }
                return false;
            case 2:
                if (sa[i] ==' ') { state = 8; continue; }
                if (sa[i] == '.') { state = 4; continue; }
                if (sa[i] >= '0' && sa[i] <= '9') continue;
                if (sa[i] == 'e' || sa[i] == 'E') { state = 5; continue; }
                return false;
            case 3:
                if (sa[i] >= '0' && sa[i] <= '9') { state = 4; continue; }
                return false;
            case 4:
                if (sa[i] == 'e' || sa[i] == 'E') { state = 5; continue; }
                if (sa[i] == ' ') { state = 8; continue; }
                if (sa[i] >= '0' && sa[i] <= '9') continue;
                return false;
            case 5:
                if (sa[i] == '+' || sa[i] == '-') { state = 6; continue; }
                if (sa[i] >= '0' && sa[i] <= '9') { state = 7; continue; }
                return false;
            case 6:
                if (sa[i] >= '0' && sa[i] <= '9') { state = 7; continue; }
                return false;
            case 7:
                if (sa[i] >= '0' && sa[i] <= '9') continue;
                if (sa[i] == ' ') { state = 8; continue; }
                return false;
            case 8:
                if (sa[i] == ' ') continue;
                return false;
            default:
                return false;
            }
        }
        if (state == 2 || state == 4 || state == 7 || state == 8) return true;
        return false;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值