题目描述
请实现一个函数用来判断字符串是否表示数值 (包括整数和小数)。
数值 (按顺序)可以分成以下几个部分:
若干空格
一个 小数 或者 整数
(可选)一个 'e'
或 'E'
,后面跟着一个 整数
若干空格
小数 (按顺序)可以分成以下几个部分:
(可选)一个符号字符('+'
或 '-'
)
下述格式之一:
至少一位数字,后面跟着一个点 '.'
至少一位数字,后面跟着一个点 '.'
,后面再跟着至少一位数字
一个点 '.'
,后面跟着至少一位数字
整数 (按顺序)可以分成以下几个部分:
(可选)一个符号字符('+'
或 '-'
)
至少一位数字
部分数值 列举如下:
["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]
部分非数值 列举如下:
["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]
示例 1:
输入: s = "0"
输出: true
示例 2:
输入: s = "e"
输出: false
示例 3:
输入: s = "."
输出: false
示例 4:
输入: s = " .1 "
输出: true
提示:
1 <= s.length <= 20
s
仅含英文字母(大写和小写),数字(0-9
),加号 '+'
,减号 '-'
,空格 ' '
或者点 '.'
。
解法
方法一:分类讨论
我们先去除字符串 $s$ 首尾的空格,此时 $i$ 和 $j$ 分别指向字符串 $s$ 的第一个非空格字符和最后一个非空格字符。
然后我们维护以下几个变量,其中:
digit
:表示是否出现过数字
dot
:表示是否出现过点
e
:表示是否出现过 e
或者 E
遍历 $s[i,..j]$ 范围内的每个字符,根据字符的类型进行分类讨论:
如果当前字符是 +
或者 -
,那么该字符必须是第一个有效字符(即空格后的第一个非空字符),或者该字符的前一个字符必须是 e
或者 E
,否则返回 false
。
如果当前字符是数字,那么我们将 digit
置为 true
。
如果当前字符是 .
,那么该字符之前不能出现过 .
或者 e
/E
,否则返回 false
,否则我们将 dot
置为 true
。
如果当前字符是 e
或者 E
,那么该字符之前不能出现过 e
/E
,并且必须出现过数字,否则返回 false
,否则我们将 e
置为 true
,并且将 digit
置为 false
,表示 e
之后必须出现数字。
如果当前字符是其它字符,那么返回 false
。
遍历结束后,我们返回 digit
,即是否出现过数字。
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为字符串 $s$ 的长度。
Python3 Java C++ Go C# Swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 class Solution :
def isNumber ( self , s : str ) -> bool :
i , j = 0 , len ( s ) - 1
while i < j and s [ i ] == " " :
i += 1
while i <= j and s [ j ] == " " :
j -= 1
if i > j :
return False
digit = dot = e = False
while i <= j :
if s [ i ] in "+-" :
if i and s [ i - 1 ] not in " eE" :
return False
elif s [ i ] . isdigit ():
digit = True
elif s [ i ] == "." :
if dot or e :
return False
dot = True
elif s [ i ] in "eE" :
if not digit or e :
return False
e , digit = True , False
else :
return False
i += 1
return digit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 class Solution {
public boolean isNumber ( String s ) {
int i = 0 , j = s . length () - 1 ;
while ( i < j && s . charAt ( i ) == ' ' ) {
++ i ;
}
while ( i <= j && s . charAt ( j ) == ' ' ) {
-- j ;
}
if ( i > j ) {
return false ;
}
boolean digit = false ;
boolean dot = false ;
boolean e = false ;
for (; i <= j ; ++ i ) {
if ( s . charAt ( i ) == '+' || s . charAt ( i ) == '-' ) {
if ( i > 0 && s . charAt ( i - 1 ) != ' ' && s . charAt ( i - 1 ) != 'e'
&& s . charAt ( i - 1 ) != 'E' ) {
return false ;
}
} else if ( Character . isDigit ( s . charAt ( i ))) {
digit = true ;
} else if ( s . charAt ( i ) == '.' ) {
if ( dot || e ) {
return false ;
}
dot = true ;
} else if ( s . charAt ( i ) == 'e' || s . charAt ( i ) == 'E' ) {
if ( ! digit || e ) {
return false ;
}
e = true ;
digit = false ;
} else {
return false ;
}
}
return digit ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 class Solution {
public :
bool isNumber ( string s ) {
int i = 0 , j = s . size () - 1 ;
while ( i < j && s [ i ] == ' ' ) {
++ i ;
}
while ( i <= j && s [ j ] == ' ' ) {
-- j ;
}
if ( i > j ) {
return false ;
}
bool digit = false , dot = false , e = false ;
for (; i <= j ; ++ i ) {
if ( s [ i ] == '+' || s [ i ] == '-' ) {
if ( i && s [ i - 1 ] != ' ' && s [ i - 1 ] != 'e' && s [ i - 1 ] != 'E' ) {
return false ;
}
} else if ( isdigit ( s [ i ])) {
digit = true ;
} else if ( s [ i ] == '.' ) {
if ( dot || e ) {
return false ;
}
dot = true ;
} else if ( s [ i ] == 'e' || s [ i ] == 'E' ) {
if ( ! digit || e ) {
return false ;
}
e = true ;
digit = false ;
} else {
return false ;
}
}
return digit ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 func isNumber ( s string ) bool {
i , j := 0 , len ( s ) - 1
for i < j && s [ i ] == ' ' {
i ++
}
for i <= j && s [ j ] == ' ' {
j --
}
if i > j {
return false
}
digit , dot , e := false , false , false
for ; i <= j ; i ++ {
if s [ i ] == '+' || s [ i ] == '-' {
if i > 0 && s [ i - 1 ] != ' ' && s [ i - 1 ] != 'e' && s [ i - 1 ] != 'E' {
return false
}
} else if s [ i ] >= '0' && s [ i ] <= '9' {
digit = true
} else if s [ i ] == '.' {
if dot || e {
return false
}
dot = true
} else if s [ i ] == 'e' || s [ i ] == 'E' {
if ! digit || e {
return false
}
digit , e = false , true
} else {
return false
}
}
return digit
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 public class Solution {
public bool IsNumber ( string s ) {
int i = 0 , j = s . Length - 1 ;
while ( i < j && s [ i ] == ' ' ) {
++ i ;
}
while ( i <= j && s [ j ] == ' ' ) {
-- j ;
}
if ( i > j ) {
return false ;
}
bool digit = false , dot = false , e = false ;
for (; i <= j ; ++ i ) {
if ( s [ i ] == '+' || s [ i ] == '-' ) {
if ( i > 0 && s [ i - 1 ] != ' ' && s [ i - 1 ] != 'e' && s [ i - 1 ] != 'E' ) {
return false ;
}
} else if ( s [ i ] >= '0' && s [ i ] <= '9' ) {
digit = true ;
} else if ( s [ i ] == '.' ) {
if ( dot || e ) {
return false ;
}
dot = true ;
} else if ( s [ i ] == 'e' || s [ i ] == 'E' ) {
if ( ! digit || e ) {
return false ;
}
e = true ;
digit = false ;
} else {
return false ;
}
}
return digit ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 class Solution {
func isNumber ( _ s : String ) -> Bool {
let chars = Array ( s )
var i = 0 , j = chars . count - 1
// Trim leading spaces
while i <= j && chars [ i ] == " " {
i += 1
}
// Trim trailing spaces
while i <= j && chars [ j ] == " " {
j -= 1
}
if i > j {
return false
}
var digit = false
var dot = false
var e = false
while i <= j {
let char = chars [ i ]
if char == "+" || char == "-" {
if i > 0 && chars [ i - 1 ] != " " && chars [ i - 1 ] != "e" && chars [ i - 1 ] != "E" {
return false
}
} else if char . isWholeNumber {
digit = true
} else if char == "." {
if dot || e {
return false
}
dot = true
} else if char == "e" || char == "E" {
if ! digit || e {
return false
}
e = true
digit = false
} else {
return false
}
i += 1
}
return digit
}
}