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;
}
}
반응형