题目链接
题目描述
有效数字(按顺序)可以分成以下几个部分:
一个 小数 或者 整数
(可选)一个 'e'
或 'E'
,后面跟着一个 整数
小数(按顺序)可以分成以下几个部分:
(可选)一个符号字符('+'
或 '-'
)
下述格式之一:
至少一位数字,后面跟着一个点 '.'
至少一位数字,后面跟着一个点 '.'
,后面再跟着至少一位数字
一个点 '.'
,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
(可选)一个符号字符('+'
或 '-'
)
至少一位数字
部分有效数字列举如下:["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
部分无效数字列举如下:["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]
给你一个字符串 s ,如果 s 是一个 有效数字 ,请返回 true 。
示例 1:
输入:s = “0”
输出:true
示例 2:
输入:s = “e”
输出:false
示例 3:
输入:s = “.”
输出:false
提示:
- 1 < = s . l e n g t h < = 20 1 <= s.length <= 20 1<=s.length<=20
- s 仅含英文字母(大写和小写),数字(
0-9
),加号'+'
,减号'-'
,或者点'.'
。
分析:
本题是一道比较复杂的模拟题,我们根据题意进行模拟即可。
首先我们先过滤一些非法字符,便于我们我后面处理
int op = 0,point = 0,e = 0,e_idx = -1,point_idx = -1;
int n = s.length();
for(int i = 0;i < n;i++){
char c = s.charAt(i);
//如果 c 是数字直接跳过本次循环
if(isdigit(c)) continue;
//如果是操作符 记录操作符的个数
if(c == '+' || c == '-'){
op++;
continue;
}
//记录小数点的个数
if(c == '.'){
point++;
//记录小数点的位置
point_idx = i;
continue;
}
//记录 e 的个数
if(c == 'E' || c == 'e'){
e++;
//记录 e 的位置
e_idx = i;
continue;
}
//如果都不是 只能是除了(E/e)之外的大小写字母,不满足要求,直接返回false
return false;
}
// 一个合法的数字中 操作符号最多两个 小数点最多一个 e最多一个 超过的都是不符合要求的 直接返回 false
if(op > 2 || point > 1 || e > 1) return false;
紧接着我们根据是否存在小数点,来分别处理 整数 和 小数,整数 和 小数 再细分为带 E/e 和 不带E/e的数。
- 整数,不带E/e
//整数不带E/e 的合法数字的形式为 (+/-)....
//由于通过先前的过滤 现在的 s 只包含操作符 (+/-) 和 数字
//操作符只能在第 0 个位置,如果在后面的位置出现了操作符 即为不合法
//用 a 记录数字个数,a必须大于0,避免出现 s = "+“ 也通过的情况
int a = 0;
for(int i = 0;i < n;i++){
char ch = s.charAt(i);
if(i == 0 && (ch =='+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
a++;
}
return a>0;
- 整数,带E/e
//此时合法数字的形式为 (+/-)....E/e (+/-)...
//用 a b分别记录两段数字个数,a 和 b都必须大于0
int a = 0,b = 0;
//只能在第0个位置有操作符,第一段的后面的位置都必须是数字,统计第一段数字的个数
for(int i = 0;i < e_idx;i++){
char ch = s.charAt(i);
if(i == 0 &&(ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
a++;
}
//只能在第e_idx+1个位置(也就是s中 E/e 后面的一个位置)有操作符,第二段的后面的位置都必须是数字,统计第二段数字的个数
for(int i = e_idx + 1;i < n;i++){
char ch = s.charAt(i);
if(i == e_idx + 1 &&(ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
b++;
}
return (a>0) && (b>0);
- 小数,不带E/e
//此时的合法数字形式为 (+/-)a.b
//小数点两边的数字,可以两个都存在,也可以只有一边有数字,不能两边都没有。即 2.3 , .3 ,2. 都合法。 . 不合法
int a = 0,b = 0;
for(int i = 0;i < point_idx;i++){
char ch = s.charAt(i);
if(i == 0 && (ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
a++;
}
for(int i = point_idx + 1;i < n;i++){
char ch = s.charAt(i);
if(!isdigit(ch)) return false;
b++;
}
return (a>0)||(b>0);
- 小数,带E/e
//此时的合法数字的形式为 (+/-)a.b E/e (+/-)c
//a 和 b可以同时存在,也可以只存在其中一个,不可以都不存在
//c 必须存在
//分别统计三段的数字 a b c 即可
int a = 0,b = 0,c = 0;
for(int i = 0;i < point_idx;i++){
char ch = s.charAt(i);
if(i == 0 && (ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
a++;
}
for(int i = point_idx + 1;i < e_idx;i++){
char ch = s.charAt(i);
if(!isdigit(ch)) return false;
b++;
}
for(int i = e_idx+1;i < n;i++){
char ch = s.charAt(i);
if(i == e_idx+1 && (ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
c++;
}
return (a>0||b>0)&&(c>0);
时间复杂度: O ( n ) O(n) O(n)
C++代码:
class Solution {
public:
bool isNumber(string s) {
int op = 0,point = 0,e = 0,e_idx = -1,point_idx = -1;
int n = s.size();
for(int i = 0;i < n;i++){
char c = s[i];
if(isdigit(c)) continue;
if(c == '+' || c == '-'){
op++;
continue;
}
if(c == '.'){
point++;
point_idx = i;
continue;
}
if(c == 'E' || c == 'e'){
e++;
e_idx = i;
continue;
}
return false;
}
if(op > 2 || point > 1 || e > 1) return false;
bool flag = point == 1;
//小数
if(flag){
//带 e 的
if(e == 1){
int a = 0,b = 0,c = 0;
for(int i = 0;i < point_idx;i++){
if(i == 0 && (s[i] == '+' || s[i] == '-')) continue;
if(!isdigit(s[i])) return false;
a++;
}
for(int i = point_idx + 1;i < e_idx;i++){
if(!isdigit(s[i])) return false;
b++;
}
for(int i = e_idx+1;i < n;i++){
if(i == e_idx+1 && (s[i] == '+' || s[i] == '-')) continue;
if(!isdigit(s[i])) return false;
c++;
}
return (a||b)&&c;
}
//不带 e 的
else{
int a = 0,b = 0;
for(int i = 0;i < point_idx;i++){
if(i == 0 && (s[i] == '+' || s[i] == '-')) continue;
if(!isdigit(s[i])) return false;
a++;
}
for(int i = point_idx + 1;i < n;i++){
if(!isdigit(s[i])) return false;
b++;
}
return a||b;
}
}
//整数
else{
if(e == 1){
int a = 0,b = 0;
for(int i = 0;i < e_idx;i++){
if(i == 0 &&(s[i] == '+' || s[i] == '-')) continue;
if(!isdigit(s[i])) return false;
a++;
}
for(int i = e_idx + 1;i < n;i++){
if(i == e_idx + 1 &&(s[i] == '+' || s[i] == '-')) continue;
if(!isdigit(s[i])) return false;
b++;
}
return a && b;
}
else{
//cout<<"不带e"<<endl;
int a = 0;
for(int i = 0;i < n;i++){
if(i == 0 && (s[i] =='+' || s[i] == '-')) continue;
if(!isdigit(s[i])) return false;
a++;
}
return a;
}
}
return true;
}
};
Java代码:
class Solution {
public boolean isdigit(char c){
return c >= '0' && c <= '9';
}
public boolean isNumber(String s) {
int op = 0,point = 0,e = 0,e_idx = -1,point_idx = -1;
int n = s.length();
for(int i = 0;i < n;i++){
char c = s.charAt(i);
if(isdigit(c)) continue;
if(c == '+' || c == '-'){
op++;
continue;
}
if(c == '.'){
point++;
point_idx = i;
continue;
}
if(c == 'E' || c == 'e'){
e++;
e_idx = i;
continue;
}
return false;
}
if(op > 2 || point > 1 || e > 1) return false;
boolean flag = point == 1;
//小数
if(flag){
//带 e 的
if(e == 1){
int a = 0,b = 0,c = 0;
for(int i = 0;i < point_idx;i++){
char ch = s.charAt(i);
if(i == 0 && (ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
a++;
}
for(int i = point_idx + 1;i < e_idx;i++){
char ch = s.charAt(i);
if(!isdigit(ch)) return false;
b++;
}
for(int i = e_idx+1;i < n;i++){
char ch = s.charAt(i);
if(i == e_idx+1 && (ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
c++;
}
return (a>0||b>0)&&(c>0);
}
//不带 e 的
else{
int a = 0,b = 0;
for(int i = 0;i < point_idx;i++){
char ch = s.charAt(i);
if(i == 0 && (ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
a++;
}
for(int i = point_idx + 1;i < n;i++){
char ch = s.charAt(i);
if(!isdigit(ch)) return false;
b++;
}
return (a>0)||(b>0);
}
}
//整数
else{
if(e == 1){
int a = 0,b = 0;
for(int i = 0;i < e_idx;i++){
char ch = s.charAt(i);
if(i == 0 &&(ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
a++;
}
for(int i = e_idx + 1;i < n;i++){
char ch = s.charAt(i);
if(i == e_idx + 1 &&(ch == '+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
b++;
}
return (a>0) && (b>0);
}
else{
int a = 0;
for(int i = 0;i < n;i++){
char ch = s.charAt(i);
if(i == 0 && (ch =='+' || ch == '-')) continue;
if(!isdigit(ch)) return false;
a++;
}
return a>0;
}
}
}
}