一、题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+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出现至少一次,并最多出现四个。 |
*? | ?后一个量词使其成为一个不贪婪的量词。它试图找到最小的匹配。 |