您的位置:首页 > Web前端

牛客网剑指offer之表示数值的字符串

2020-06-05 06:02 120 查看

题目描述:

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

这是牛客网上剑指offer专栏的一道题 事实上自己之前刷leetcode的时候也遇到了这道题 当时觉得情况太复杂 直接看的题解 题解中有人提到了有限状态机的做法 自己直接被名字吓到了(事实上没那么可怕。。) 直接复制提交也没细看具体做法 后来自己刷题过程中又遇到了一些用有限状态机解决的问题 也算是对有限状态机有了初步的了解 这次再次遇到这道题 尝试用有限状态机解决 最后还做了出来 这里交代一下做法
我们用肉眼判断字符串可不可以转化为数字的时候 其实就暗含了一些规则 比如
12e+4.3 不能转化为数值 因为e之后不能跟小数;
1.2.3 不能转化为数值 因为出现了两次 ‘.’
12e 不能转化为数值 因为出现了e,那么后面就一定要有整数;
按照字符的具体位置 其可以分为九种状态,分别是:

status:
1:start //最初状态
2:+ -符号
3:e/E之前的整数位
4:e之前的小数点位
5:e之前的小数位
6:e/E
7:e之后的+ -符号
8:e之后的数字
9:end
其中状态可以按照以下规则转化:
1->2/3/4/*字符串最开始只能是2、3、4三种状态 否则就是false
值得注意的是 数值可以以小数点开始 比如.34就代表0.34*/
2->3/4 //+ -符号后面可以跟数字 也可以跟小数点(理由同上)
3->3/4/6/9 //整数后可以继续是整数、小数点、e/E或者直接结束
4->5 //小数点之后只能跟小数位
5->6/9//小数位后可以跟 e/E或者直接结束
6->7/8 // e/E之后可以跟+ -符号 或者数字
7->8 //符号后面跟数字
8->8/9 //数字后面跟数字 或者直接结束

以上状态划分有几点要注意
为什么在 e/E之前要把数字分为 整数位和小数位两种状态呢 e/E之后就不分了呢?
因为 整数位可以跟 小数点 而小数位 是不能的 防止出现 1.2.3 这种情况 而e/E之后是不会存在小数点的;
下面是具体实现代码:

public class Solution {
//判断是否是数字
public boolean isNum(char c)
{
return c>='0'&&c<='9';
}
public boolean isNumeric(char[] str) {
//一开始是状态“1”
String status="1";
//根据当前状态以及当前字符 更新下一状态
for(int i=0;i<str.length;i++)
{
char c=str[i];
switch(status)
{
case "1":
{
if(c=='+'||c=='-')
status="2";
else if(isNum(c))
status="3";
else if(c=='.')
status="4";
else
return false;
break;
}
case "2":
{
if(isNum(c))
status="3";
else if(c=='.')
status="4";
else
return false;
break;
}
case "3":
{
if(isNum(c))
status="3";
else if(c=='.')
status="4";
else if(c=='e'||c=='E')
status="6";
else
return false;
break;
}
case "4":
{
if(isNum(c))
status="5";
else
return false;
break;
}
case "5":
{
if(isNum(c))
status="5";
else if(c=='e'||c=='E')
status="6";
else
return false;
break;
}
case "6":
{
if(c=='+'||c=='-')
status="7";
else if(isNum(c))
status="8";
else
return false;
break;
}
case "7":
{
if(isNum(c))
status="8";
else
return false;
break;
}
case "8":
{
if(!isNum(c))
return false;
break;
}
default:
return false;
}
//当前字符为最后一位 且当前状态为“3” “5” “8”时 返回true
if(i==str.length-1&&(status.equals("3")||status.equals("5")||status.equals("8")))
return true;
}
return false;
}
}

不过上面状态划分是还有一点儿瑕疵 无法解决 +001.5这种情况 也就是没有考虑无意义0的情况 如果考虑的话 要麻烦一点儿 因为通过了所有测试样例 所以也懒得搞了 我估计这道题要考察的可能就是这种思想吧

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: