原题目
验证给定的字符串是否可以解释为十进制数字。
例如:
“0” => true
" 0.1 " => true
“abc” => false
“1 a” => false
“2e10” => true
" -90e3 " => true
" 1e" => false
“e3” => false
" 6e-1" => true
" 99e2.5 " => false
“53.5e93” => true
" --6 " => false
“-+3” => false
“95a54e53” => false
说明: 我们有意将问题陈述地比较模糊。在实现代码之前,你应当事先思考所有可能的情况。这里给出一份可能存在于有效十进制数字中的字符列表:
数字 0-9
指数 - “e”
正/负号 - “+”/"-"
小数点 - “.”
当然,在输入中,这些字符的上下文也很重要。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-number
题目分析
方法一:混乱法:
debug每次将没考虑的情况添上去,最后自己一片混乱。
方法二:直接法:
定个返回标志flag=false,代表遍历到当前位置数字是否有效
一个正确的数字,从开始到结尾的判断如下
条件 | while | if | while | if | while | if(flag)|(if|while) | while |
---|---|---|---|---|---|---|---|
字符 | 空格 | ± | 数字 | 小数点 | 数字 | e|(±|数字) | 空格 |
flag | false | false | true | 取决于前面 | true | false|false|true | 取决于前面 |
return s[i]!=’\0’&&flag=true
方法三:状态机:
将其分为多种状态,默认从状态0开始,利用当前状态和当前字符条件来判断将跳转到下个状态n,将当前状态下,不能继续跳转的字符条件的下一状态设为-1,直接返回false,如果能跳转到最后,判断其是否在几个有效的状态下
状态\下一状态条件 | blank(0) | ±(1) | 0~9(2) | dot(3) | e(4) | ohter(5) |
---|---|---|---|---|---|---|
0 | 0 | 1 | 3 | 2 | -1 | -1 |
1 | -1 | -1 | 3 | 2 | -1 | -1 |
2 | -1 | -1 | 4 | -1 | -1 | -1 |
3 | 8 | -1 | 3 | 4 | 5 | -1 |
4 | 8 | -1 | 4 | -1 | 5 | -1 |
5 | -1 | 6 | 7 | -1 | -1 | -1 |
6 | -1 | -1 | 7 | -1 | -1 | -1 |
7 | 8 | -1 | 7 | -1 | -1 | -1 |
8 | 8 | -1 | -1 | -1 | -1 | -1 |
状态是否有效 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
false(0)/true(1) | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
完整代码
方法一:
bool isNumber(char * s){
int i=0,j=strlen(s)-1;
int size_dot=0,site_dot=0;
int size_e=0,site_e=j+1;
int size_sum=0;
while(s[i]==' ')i++;
if(i>j)return false;
while(s[j]==' ')j--;
int left=i,right=j;
if(i==j&&s[i]>='0'&&s[i]<='9')return true;
else if(i==j)return false;
while(i<=j)
{
if(s[i]!='+'&&s[i]!='-'&&s[i]!='.'&&s[i]!='e'&&(s[i]<'0'||s[i]>'9'))
return false;
else if((s[i]=='+'||s[i]=='-')&&(i!=left&&s[i-1]!='e'||i==right))
return false;
else if(s[i]=='.'&&(i!=left&&i!=right&&(s[i-1]<'0'||s[i-1]>'9'||s[i+1]<'0'||s[i+1]>'9')&&(s[i-1]!='+'&&s[i-1]!='-')&&s[i+1]!='e'||i==left&&s[i+1]=='e'))
{
return false;
}
else if(s[i]=='.')
{
size_dot++;
site_dot=i;
if(size_dot>1||site_e<site_dot)
return false;
}
else if(s[i]=='e'&&(i==left||i==right||(s[i-1]<'0'||s[i-1]>'9')&&s[i-1]!='.'||((s[i+1]<'0'||s[i+1]>'9')&&s[i+1]!='-'&&s[i+1]!='+')))
{return false;}
else if(s[i]=='e')
{
size_e++;
site_e=i;
if(size_e>1||site_e<site_dot)
return false;
}
else if(s[i]<='9'&&s[i]>='0')
{
size_sum++;
}
i++;
}
if(size_sum==0)return false;
return true;
}
方法二:
bool isNumber(char * s){
int i=0;
bool flag=false;
while(s[i]==' ')
{
i++;
}
if(s[i]=='+'||s[i]=='-')
{
i++;
}
while(isdigit(s[i]))
{
flag=true;
i++;
}
if(s[i]=='.')
{
i++;
}
while(isdigit(s[i]))
{
flag=true;
i++;
}
if(flag==true&&s[i]=='e')
{
i++;
if(s[i]=='+'||s[i]=='-')
{
i++;
}
flag=false;
while(isdigit(s[i]))
{
flag=true;
i++;
}
}
while(s[i]==' ')
{
i++;
}
return s[i]=='\0'&&flag==true;
}
方法三:
class Solution {
public:
int fun(char c){
if(isdigit(c)){
return 2;
}
switch(c){
case ' ':return 0;
case '-':return 1;
case '+':return 1;
case '.':return 3;
case 'e':return 4;
default:return 5;
}
}
bool isNumber(string s) {
//行:状态0-7 列:下一状态条件:blank,_+,0~9,dot,e,other
vector<vector<int>>vec={{0,1,3,2,-1,-1},
{-1,-1,3,2,-1,-1},
{-1,-1,4,-1,-1,-1},
{8,-1,3,4,5,-1},
{8,-1,4,-1,5,-1},
{-1,6,7,-1,-1,-1},
{-1,-1,7,-1,-1,-1},
{8,-1,7,-1,-1,-1},
{8,-1,-1,-1,-1,-1}};
vector<bool>flag = {0,0,0,1,1,0,0,1,1};
int j = 0;
for(auto c : s){
j = vec[j][fun(c)];
if(j == -1)return false;
}
return flag[j];
}
};