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

题目描述:

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+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的情况 如果考虑的话 要麻烦一点儿 因为通过了所有测试样例 所以也懒得搞了 我估计这道题要考察的可能就是这种思想吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值