본문 바로가기

카테고리 없음

[leetcode] 65. Valid Number (Java)

state machine 을 이용해서 문제를 해결한다.

NumberState 라는 interface를 정의해서 canEnd, toNextState(char c) method를 정의한다.
canEnd는 현재 state가 종료가능한 state인지 return 하는 method이고,
toNextState(char c)는 다음 state를 return 하는 method이다.
toNextState에서 다음 state로 갈 수 없는 경우에는 Exception을 발생시킨다.

String을 차례대로 읽으면서, Start state부터 시작해서 state를 변경시켜준다.

Start  -> Sign, BeforeDotNumber, StartWithDot, AfterDotNumber
Sign -> StartWithDot, BeforeDotNumber
BeforeDotNumber -> Dot, BeforeDotNumber, ExponentStart
StartWithDot -> AfterDotNumber
AfterDotNumber -> AfterDotNumber, ExponentStart 
ExponentStart -> ExpoentSign, ExponentNumber
ExponentNumber -> ExponentNumber

interface NumberState {
    boolean canEnd();

    NumberState toNextState(char c);

    default boolean isDigit(char c) {
        int num = c - '0';
        return num >= 0 && num <= 9;
    }

    default boolean isE(char c) {
        return (c == 'E' || c == 'e');
    }
}

class Start implements NumberState {

    @Override
    public boolean canEnd() {
        return false;
    }

    @Override
    public NumberState toNextState(char c) {
        if (c == '+' || c == '-') {
            return new Sign();
        } else if (isDigit(c)) {
            return new BeforeDotNumber();
        } else if (c == '.') {
            return new StartWithDot();
        }
        throw new IllegalArgumentException();
    }

}

class Sign implements NumberState {
    @Override
    public boolean canEnd() {
        return false;
    }

    @Override
    public NumberState toNextState(char c) {
        if (isDigit(c)) {
            return new BeforeDotNumber();
        } else if (c == '.') {
            return new StartWithDot();
        }
        throw new IllegalArgumentException();
    }

}

class BeforeDotNumber implements NumberState {

    @Override
    public boolean canEnd() {
        return true;
    }

    @Override
    public NumberState toNextState(char c) {
        if (isDigit(c)) {
            return this;
        } else if (c == '.') {
            return new Dot();
        } else if (c == 'E' || c == 'e') {
            return new ExponentStart();
        }
        throw new IllegalArgumentException();
    }

}

class StartWithDot implements NumberState {

    @Override
    public boolean canEnd() {
        return false;
    }

    @Override
    public NumberState toNextState(char c) {
        if (isDigit(c)) {
            return new AfterDotNumber();
        }
        throw new IllegalArgumentException();
    }

}

class Dot implements NumberState {

    @Override
    public boolean canEnd() {
        return true;
    }

    @Override
    public NumberState toNextState(char c) {
        if (isDigit(c)) {
            return new AfterDotNumber();
        } else if (isE(c)) {
            return new ExponentStart();
        }
        throw new IllegalArgumentException();
    }
}

class AfterDotNumber implements NumberState {
    @Override
    public boolean canEnd() {
        return true;
    }

    @Override
    public NumberState toNextState(char c) {
        if (isDigit(c)) {
            return this;
        } else if (c == 'e' || c == 'E') {
            return new ExponentStart();
        }
        throw new IllegalArgumentException();
    }

}

class ExponentStart implements NumberState {

    @Override
    public boolean canEnd() {
        return false;
    }

    @Override
    public NumberState toNextState(char c) {
        if (c == '+' || c == '-') {
            return new ExponentSign();
        } else if (isDigit(c)) {
            return new ExponentNumber();
        }
        throw new IllegalArgumentException();
    }

}

class ExponentSign implements NumberState {

    @Override
    public boolean canEnd() {
        return false;
    }

    @Override
    public NumberState toNextState(char c) {
        if (isDigit(c)) {
            return new ExponentNumber();
        }
        throw new IllegalArgumentException();
    }

}

class ExponentNumber implements NumberState {

    @Override
    public boolean canEnd() {
        return true;
    }

    @Override
    public NumberState toNextState(char c) {
        if (isDigit(c)) {
            return this;
        }
        throw new IllegalArgumentException();
    }

}

class Solution {
    public boolean isNumber(String s) {
        NumberState state = new Start();
        try {
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                state = state.toNextState(c);
            }
            return state.canEnd();
        } catch (Exception e) {
        }
        return false;
    }
}

 

 

 

반응형