剑指 Offer 20. 表示数值的字符串

题目描述

请实现一个函数用来判断字符串是否表示 数值 (包括整数和小数)。

数值 (按顺序)可以分成以下几个部分:

  1. 若干空格
  2. 一个  小数  或者  整数
  3. (可选)一个 $’e’$ 或 $’E’$ ,后面跟着一个  整数
  4. 若干空格

小数 (按顺序)可以分成以下几个部分:

  1. (可选)一个符号字符($’+’$ 或 $’-‘$)
  2. 下述格式之一:
    1. 至少一位数字,后面跟着一个点 $’.’$
    2. 至少一位数字,后面跟着一个点 $’.’$ ,后面再跟着至少一位数字
    3. 一个点 $’.’$ ,后面跟着至少一位数字

整数 (按顺序)可以分成以下几个部分:

  1. (可选)一个符号字符($’+’$ 或 $’-‘$)
  2. 至少一位数字

部分 数值 列举如下:

  • $[“+100”, “5e2”, “-123”, “3.1416”, “-1E-16”, “0123”]$

部分 非数值 列举如下:

  • $[“12e”, “1a3.14”, “1.2.3”, “+-5”, “12e+5.4”]$

示例 1:

1
2
输入:s = "0"
输出:true

示例 2:

1
2
输入:s = "e"
输出:false

示例 3:

1
2
输入:s = "."
输出:false

示例 4:

1
2
输入:s = "    .1  "
输出:true

提示:

  • $1 <= s.length <= 20$
  • $s$ 仅含英文字母(大写和小写),数字($0-9$),加号 $’+’$ ,减号 $’-‘$ ,空格 $’ ‘$ 或者点 $’.’$ 。

算法

(模拟) $O(n)$

算法步骤:

  1. 先去除行首和行尾空格;
  2. 行首如果有一个正负号,直接忽略;
  3. 如果字符串为空或只有一个’.’,则不是一个合法数;
  4. 循环整个字符串,去掉以下几种情况:
    (1) ‘.’或’e’多于1个;
    (2) ‘.’在’e’后面出现;
    (3) ‘e’后面或前面为空,或者’e’前面紧跟着’.’;
    (4) ‘e’后面紧跟着正负号,但正负号后面为空;
  5. 剩下的情况都合法;

时间复杂度

$O(n)$

空间复杂度

$O(1)$

C++ 代码

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
49
50
51
52
class Solution {
public:
bool isNumber(string s) {
/* 1. 去前后空格 */
// 去掉前空格
int i = 0;
while (i < s.size() && s[i] == ' ') i ++;
// 去掉前后空格
int j = s.size() - 1;
while (j >= 0 && s[j] == ' ') j -- ;
// 删完空格后字符串不合法
if (i > j) return false;
s = s. substr(i, j - i + 1);

/* 2. 行首如果有一个正负号直接忽略 */
if (s[0] == '+' || s[0] == '-') s = s.substr(1);
/* 3. 如果字符串为空,或者只有一个 .,则不是一个合法数 */
if (s.empty() || s[0] == '.' && s.size() == 1) return false; // +, -, .

/* 4. 循环整个字符串,去掉以下几种情况:
(1) '.'或'e'多于1个;
(2) '.'在'e'后面出现;
(3) 'e'后面或前面为空,或者'e'前面紧跟着'.';
(4) 'e'后面紧跟着正负号,但正负号后面为空; */
// 字符串中点和 e 的数量
int dot = 0, e = 0;
for (int i = 0; i < s.size(); i ++ )
{
if (s[i] >= '0' && s[i] <= '9') ;
else if (s[i] == '.')
{
dot ++ ;
if (e || dot > 1) return false; // 21.1.1.2, 12e122.22
}
else if (s[i] == 'e' || s[i] == 'E')
{
e ++ ;
if (i + 1 == s.size() || !i || e > 1 || i == 1 && s[0] == '.') return false;
if (s[i + 1] == '+' || s[i + 1] == '-')
{
if (i + 2 == s.size()) return false; // 122e+ 或 122e-
i ++ ;
}
}
// 不合法的字符就直接返回 false
else return false;
}

/* 5. 其余情况都合法 */
return true;
}
};
Author: tonngw
Link: https://tonngw.com/2022/07/09/剑指 Offer/剑指 Offer 20. 表示数值的字符串/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.