剑指offer:JZ53 表示数值的字符串

描述

请实现一个函数用来判断字符串str是否表示数值(包括科学计数法的数字,小数和整数)。

科学计数法的数字(按顺序)可以分成以下几个部分:
1.若干空格
2.一个整数或者小数
3.(可选)一个 ‘e’ 或 ‘E’ ,后面跟着一个整数(可正可负)
4.若干空格

小数(按顺序)可以分成以下几个部分:
1.若干空格
2.(可选)一个符号字符(’+’ 或 ‘-’)
3. 可能是以下描述格式之一:
3.1 至少一位数字,后面跟着一个点 ‘.’
3.2 至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
3.3 一个点 ‘.’ ,后面跟着至少一位数字
4.若干空格

整数(按顺序)可以分成以下几个部分:
1.若干空格
2.(可选)一个符号字符(’+’ 或 ‘-’)
3. 至少一位数字
4.若干空格

例如,字符串["+100",“5e2”,"-123",“3.1416”,"-1E-16"]都表示数值。
但是[“12e”,“1a3.14”,“1.2.3”,“±5”,“12e+4.3”]都不是数值。

提示:
1.1 <= str.length <= 20
2.str 仅含英文字母(大写和小写),数字(0-9),加号 ‘+’ ,减号 ‘-’ ,空格 ’ ’ 或者点 ‘.’ 。
3.如果怀疑用例是不是能表示为数值的,可以使用python的print(float(str))去查看

示例

input1:		"123.45e+6"
output1:	true

input2:		"1.2.3"
output2:	false

input3:		"."
output3:	false

input4:		"    .2  "
output4:	true

思路

本题相当于判断一个字符串能否转为浮点数类型的数字,可以从头到尾进行遍历并判断,或者参考Double.parseDouble(String s)的源码,或者直接调用JavaAPI/使用有限状态机匹配,后两种方法参考@小桥流水少年梦的剑指offer题解

1、从头到尾进行遍历

本解法的思路是:
(1)去除字符串的前后空格,使用带有默认值的sig = -2来标记第一个字符是否是符号位,使用i = 0来记录字符串的当前索引
(2)字符串长度为0,则不是浮点
(3)当第一个字符是符号位时,若字符串等于一个符号位的字符,则不是浮点;否则,sig = 0表明第一个字符时符号位,继续往下查找
(4)查找字符串中的./E/e,若出现非数字则不是浮点
(5)若是纯数字,则肯定时浮点数
(6)索引指向.,则判断边界情况:./+./-.不是浮点,.后面时纯数字则是浮点
(7)索引指向E/e,表明前面小数部分检测通过,需要考虑边界情况:字符串等于字符E、小数+EE+正数、符号位+E时都不符合浮点
(8)判断E/e后面的整数,边界情况:只有符号位、或者非数字则不是浮点

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param str string字符串 
     * @return bool布尔型
     */
    public boolean isNumeric (String str) {
        // write code here
        str = str.trim(); //去掉前后的空格
        int sig = -2; //记录前面小数部分是否有+/-号,以排除+./-e等情况
        int i = 0, len = str.length();
        char c = '#';
        if(len == 0) return false; //空字符串
        //若第一个字符是符号位,则给sig赋值0
        if(str.charAt(0) == '+' || str.charAt(0) == '-'){
            if(len == 1) return false;//只有一个符号位
            sig = 0;
            i ++;
        }
        //寻找字符串中的./E/e
        while(i < len && (c = str.charAt(i)) != '.' && c != 'e' && c != 'E'){
            if(c < '0' || c > '9') return false;
            i ++;
        }
        if(i == len) return true; //纯数字时
        if(c == '.'){ //索引指向了'.'
            i ++; //i指向.的下一位
            if(i == len && (i == 1 || sig == 0)) return false;//三种情况:"."、"+."、"-."
            while(i < len && (c = str.charAt(i)) != 'E' && c != 'e'){
                if(c < '0' || c > '9') return false;
                i ++;
            }
            if(i == len) return true; //.后是纯数字
            //或者索引指向'E'/'e'
        }
        //索引指向了'E'/'e'
        if(i == 0 || i == len-1 || sig + 1 == i) return false;//单独E、E前面/后面为空、"+e5"
        i ++; //索引指向了'E'/'e'后面的字符
        if(str.charAt(i) == '+' || str.charAt(i) == '-') i++;
        if(i == len) return false; //例如,"7e+"、"7e"
        while(i < len){
            c = str.charAt(i);
            if(c < '0' || c > '9') return false;
            i ++;
        }
        return true;
    }
}

在这里插入图片描述

2、使用Java的API

(1)正则表达式

正则符号含义说明
^匹配输入字符串的开始位置
$匹配输入字符串的结束位置
.任意字符除开 \n
\d数字
*0次或者多次相当于{0,}
+1次或者多次相当于{1,}
?0次或者1次相当于{0,1}
(pattern)匹配 pattern 并获取这一匹配
import java.util.*;
public class Solution {
    public boolean isNumeric (String str) {
        return str.trim().matches("[+-]?(\\d+|\\.\\d+|\\d+\\.\\d*)([eE][+-]?\\d+)?");
        //Pattern.matches("[+-]?(\\d+|\\.\\d+|\\d+\\.\\d*)([eE][+-]?\\d+)?",str);//java.util.regex.*;
    }
}

在这里插入图片描述
(2)Double.parseDouble(String s)

public class Solution {
    public boolean isNumeric (String str) {
        try{
            Double.parseDouble(str);//转化失败时会抛出异常
            return true;
        }catch(Exception e){
            return false;
        }
    }
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值