题目来自LeetCode,链接:面试题20. 表示数值的字符串。具体描述为:
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、“±5”、"-1E-16"及"12e+5.4"都不是。
先给出一种比较暴力的解法,就是根据e
先分割字符串,结果会有一个或两个字符串:
时间复杂度和空间复杂度均为 O ( n ) O(n) O(n)。
JAVA版代码如下:
class Solution {
private char[] chars;
private boolean isDigits(int start, int end, boolean prev) {
if (start >= chars.length || end >= chars.length || start > end) {
return false;
}
if (chars[start] == '+' || chars[start] == '-') {
return isDigits(start + 1, end, prev);
}
if (!((chars[start] >= '0' && chars[start] <= '9') || (chars[start] == '.' && end - start >= 1))) {
return false;
}
boolean findPoint = prev == false;
for (int i = start; i <= end; ++i) {
if (chars[i] == '.') {
if (findPoint) {
return false;
}
else {
findPoint = true;
}
}
else if (!(chars[i] >= '0' && chars[i] <= '9')) {
return false;
}
}
return true;
}
public boolean isNumber(String s) {
chars = s.strip().toCharArray();
if (chars.length == 0) {
return false;
}
int end1 = 0;
while (end1 < chars.length && chars[end1] != 'e' && chars[end1] != 'E') {
++end1;
}
--end1;
if (end1 == chars.length - 1) {
return isDigits(0, end1, true);
}
else {
return isDigits(0, end1, true) && isDigits(end1 + 2, chars.length - 1, false);
}
}
}
提交结果如下:
然后是有限状态机的方法,各个状态的意义见这里。
JAVA版代码如下:
class Solution {
private int getIdx(char c) {
switch (c) {
case ' ' : return 0;
case '+' :
case '-' : return 1;
case '.' : return 3;
case 'e' : return 4;
default :
if (c >= '0' && c <= '9') {
return 2;
}
return -1;
}
}
public boolean isNumber(String s) {
char[] chars = s.toCharArray();
int[][] transfer = new int[][]{{ 0, 1, 6, 2,-1},
{-1,-1, 6, 2,-1},
{-1,-1, 3,-1,-1},
{ 8,-1, 3,-1, 4},
{-1, 7, 5,-1,-1},
{ 8,-1, 5,-1,-1},
{ 8,-1, 6, 3, 4},
{-1,-1, 5,-1,-1},
{ 8,-1,-1,-1,-1}};
int state = 0, idx = 0;
for (char c : chars) {
idx = getIdx(c);
if (idx < 0) {
return false;
}
state = transfer[state][idx];
if (state < 0) {
return false;
}
}
// 最后多加一个空格以统一处理
state = transfer[state][0];
return state == 8;
}
}
提交结果如下:
Python版代码如下:
class Solution:
def isNumber(self, s: str) -> bool:
transfer = [[ 0, 1, 6, 2,-1],
[-1,-1, 6, 2,-1],
[-1,-1, 3,-1,-1],
[ 8,-1, 3,-1, 4],
[-1, 7, 5,-1,-1],
[ 8,-1, 5,-1,-1],
[ 8,-1, 6, 3, 4],
[-1,-1, 5,-1,-1],
[ 8,-1,-1,-1,-1]]
def getIdx(c):
if c == ' ':
return 0
if c == '+' or c == '-':
return 1
if c >= '0' and c <= '9':
return 2
if c == '.':
return 3
if c == 'e':
return 4
return -1
state, idx = 0, 0
for c in s:
idx = getIdx(c)
if idx < 0:
return False
state = transfer[state][idx]
if state < 0:
return False
return transfer[state][0] == 8
提交结果如下: