안녕하세요!
오늘은 5월 3주차 첫번째 알고리즘인 Valid Number 풀이를 적어보겠습니다.
요약
주어진 문자열 s
가 유효한 Integer
또는 Decimal
인지 확인하여 true
, false
를 return하는 문제입니다.
.
,e
를 포함하면 그것을 기준으로 앞, 뒤로 문자열을 나눈 후 앞과 뒤의 문자열의 유효성을 검사해주었습니다.
하지만.. 경우의 수가 너무너무 많았고 저는 자바가 저보다 똑똑한 것을 3시간만에 알아차렸습니다.
3시간동안 삽질을하다가 Double 자료형에
parseDouble
이라는 아주 멋진 함수가 있다는 것을 알게됩니다.
Double.parseDouble(s)
로 모든 경우의 유효성 검사가 가능했고,infinity
인 경우만 필터링해주면 되었습니다. Accept 를 받았죠.
하지만.. 알고리즘을 푸는 이유는 내장 함수를 최대한 안쓰기 위함 아니겠습니까..?
그래서 눈물을 머금고 다시 생각해봤습니다.
최근에 세번째까지 온 문제가 드물었는데, 이 문제는 어려웠습니다.. 🥲
s
의 앞 / 뒤에 공백이 있는 경우도 있기 때문에,trim()
을 사용해서 앞 / 뒤 공백을 지워준 후dot
,digit
,exp
의boolean
변수를 설정해 맨 처음부터 유효성 검사를 해주었습니다.
정말 오래 시간을 소요해서 드디어 로직을 짜고 Accept 를 받았습니다.
이제부터는 로직을 조금 더 자세하게 설명하겠습니다.
String string = s.toLowerCase().trim();
boolean dot = false, exp = false, digit = false;
s
가 대문자가 포함되어있는 경우도 있기 때문에, toLowerCase()
로 소문자로 변경해주고 trim()
을 사용해 앞 / 뒤의 공백을 제거했습니다.
그리고 .
이 나타나는 것을 체크하는 dot
, e
가 나타나는 것을 체크하는 exp
, 숫자가 나타나는 것을 체크하는 digit
변수를 설정합니다.
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
// ...
}
문자열의 처음부터 유효성 검사를 할 것이기 때문에 for문을 순회합니다.
그리고 해당 위치에 해당하는 문자를 c
에 저장합니다.
if (Character.isDigit(c)) digit = true;
c
가 숫자인 경우에 digit
을 true
로 설정합니다.
else if (c == '.') {
if (exp || dot) return false;
dot = true;
}
c
가 .
인 경우는 소수인 경우입니다.
문제에서 e
는 Integer
로 취급한다고 했기 때문에 e
가 true
라면 유효하지 않는 문자열이고, 한 문자열에 .
가 여러개 있어도 유효하지 않는 문자열입니다.
때문에 해당 경우에 false
를 return 하고 조건에 해당하지 않는다면 dot
을 true
로 설정합니다.
else if (c == 'e') {
if (exp || digit == false) return false;
exp = true;
digit = false;
}
c
가 e
인 경우는 정수인 경우입니다.
그리고 e
표기법인 경우에는 e
의 앞 / 뒤에 모두 숫자가 포함되어야하기 때문에 digit
이 false
라면 유효하지 않는 문자열입니다.
e
가 여러번 나와도 유효하지 않습니다.
e
는 .
이 표시되는 경우도 있기 때문에 dot
는 조건에 없습니다.
조건을 체크한 후에 유효하지 않는 조건에 해당되지 않는다면 exp
를 true
로 설정하고, digit
을 false
로 설정합니다.
왜냐하면 e
뒷부분에 + / - / .
들이 나와도 유효하기 때문에 초기화해주는 것입니다.
else if (c == '+' || c == '-') {
if (i > 0 && string.charAt(i - 1) != 'e') return false;
}
c
가 연산자일 경우는 해당 문자 앞에 e
가 있거나 문자열의 가장 처음에만 가능합니다.
따라서 조건에 맞다면 false
를 return 하고, 따로 체크는 해주지 않아도 됩니다.
else return false;
위의 조건들에 모두 해당하지 않는다면 유효하지 않은 알파벳이 포함되어있는 것이므로 false
를 return 합니다.
class Solution {
public boolean isNumber(String s) {
String string = s.toLowerCase().trim();
boolean dot = false, exp = false, digit = false;
for (int i = 0; i < string.length(); i++) {
char c = string.charAt(i);
if (Character.isDigit(c)) digit = true;
else if (c == '.') {
if (exp || dot) return false;
dot = true;
}
else if (c == 'e') {
if (exp || digit == false) return false;
exp = true;
digit = false;
}
else if (c == '+' || c == '-') {
if (i > 0 && string.charAt(i - 1) != 'e') return false;
}
else return false;
}
return digit;
}
}
약 5시간동안 알고리즘을 푼 것 같은데요.
다 풀고 나니까 뿌듯합니다!
저는 이제 알고리즘에 시간을 소요하느라 못한 나머지 공부를 지금 하러가야겠습니다.
이번 포스팅도 읽어주셔서 감사합니다 :)