【剑指offer】表示数值的字符串

一、题目描述

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

二、思路分析及代码实现

这道题的思路有很多,参考了很多大佬写的题解,下面就介绍几个自己可以看懂的方法:

方法一:正则表达式

该方法是自己参考了别人的想法之后写的,需要注意的有以下几点:

  • “E”或“e”前面一定存在小数部分或整数部分
  • 若存在“.”,则小数部分和整数部分不同时为空
public class Solution {
    public boolean isNumeric(char[] str) {
        String s=String.valueOf(str);
        return s.matches("[\\+\\-]?(\\d*\\.\\d+|\\d+)([eE][\\+\\-]?\\d+)?");
    }
}

方法二:异常捕获

Double.parseDouble方法是把数字类型的字符串,转换成double类型

public class Solution {
    public boolean isNumeric(char[] str) {
        String s = new String(str);
        try{
            double d = Double.parseDouble(s);
        }catch (Exception e) {
            return false;
        }
        return true;
    }
}

方法三:

一个数值包括整数部分A、小数部分B和指数部分C。而我们常见的数值形式为ABC\AB\AC\BC\A\B,也就是说指数部分前面必须有数。整数部分为有符号数,小数部分为无符号数而指数部分为有符号数。因此我们需要添加两个函数,分别判断当前字符串为有符号数scanInteger()和无符号数scanUnsignedInteger();
1、 扫描字符串,判断当前字符串中是否存在有符号数,
2、若遇到".",则后面接的应该是小数部分,应该是一个无符号数;

  • 小数部分和整数部分可以都存在,也可以只存在一个。
  • 但是若指数部分存在,则前面必须存在指数或小数。

3、 若遇到‘E’或‘e’,则为指数部分,应该是一个有符号数。

public class Solution {
    private int index=0;
    public boolean isNumeric(char[] str) {
      if(str.length<1)
        return false;
      //判断整数部分是否为有符号数
      boolean flag=scanInteger(str);
      //判断整数后面接的是小数部分还是指数部分
      //如果出现'.',接下来为数字的小数部分
      if(index<str.length&&str[index]=='.'){
        index++;
        /*
        1、小数可以没有整数部分,如.123
        2、小数可以没有小数部分,如123
        3、可以既有整数部分又有小数部分。
        */
        flag=scanUnsignedInteger(str)||flag;
      }
      //判断指数部分
      if(index<str.length&&(str[index]=='e'||str[index]=='E')){
        //指数部分为有符号数
        index++;
        flag=flag&&scanInteger(str);
      }
      return flag&&index==str.length;
    }
    public boolean scanInteger(char[] str){
      if(index<str.length&&(str[index]=='+'||str[index]=='-'))
        index++;
      return scanUnsignedInteger(str);
    }
    public boolean scanUnsignedInteger(char[] str){
      //是否存在小数部分
      int start=index;
      //每一位均为数字,则为无符号数
      while(index<str.length&&str[index]>='0'&&str[index]<='9'){
        index++;
      }
      return index>start;  
    }
}

运行时间:15ms
运行内存:9272k

注意事项:

  • 在判断小数部分时,flag=scanUnsignedInteger(str)||flag的判断顺序不可以交换,若交换顺序,则当整数部分为真时,则不对小数部分进行判断;
  • 指数部分的判断必须是在存在小数部分或整数部分情况下进行的,因此指数部分的判断是flag=flag&&scanInteger(str);

附正则表达式的基本知识:

1、常见的匹配符号:

正则表达式描述
.匹配任意字符
^匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与”\n”或”\r”之后的位置匹配。
$匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与”\n”或”\r”之前的位置匹配。
[abc]集定义,可以匹配字母A或B或C。例如,”[abc]”匹配”jian”中的”a”。
[abc] [vz]集定义,可以匹配或B或C,接着为v或z
[^abc]向字符集。匹配未包含的任何字符。例如,”[^abc]”匹配”plain”中”p”,”l”,”i”,”n”。
[a-d1-7]范围:从1到7 a和d和数字之间的匹配信,但不能匹配D1
X/Z查找X或Z
xz发现X直接跟着Z

2、元字符

正则表达式描述
\d数字字符匹配。等效于 [0-9]。
\D非数字字符匹配。等效于 [^0-9]。
\s匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。
\S匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。
\w垂直制表符匹配。与 \x0b 和 \cK 等效。
\W匹配任何字类字符,包括下划线。与”[A-Za-z0-9_]”等效。
\b匹配一个单词边界,单词字符是 [a-zA-Z0-9_]

3、量化

正则表达式描述例子
*出现零次或更多次,等效于{0,} ,例如,jia* 匹配”ji”和”jian”X *0个或多个字母X,*找到任何字符序列
+发生一次或多次,是{1,}的缩写 {1,}X+ 找到一个或几个字母X
没有发生次或一次,?是{0,1}的缩写。X? 未找到或只有一个字母X
{X}非负整数。正好匹配 X 次。例如,”o{2}”与”Bob”中的”o”不匹配,但与”food”中的两个”o”匹配。\d{3}搜索三位数字,.{10}对于长度为10的任何字符序列。
{X,Y}X和Y之间发生\d{1,4}\d出现至少一次,并最多出现四个。
*??后一个量词使其成为一个不贪婪的量词。它试图找到最小的匹配。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值