剑指offer-判断字符串是否表示数值
题目:表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
思路分析:
问题就是判断给出的字符串是否能合法地表示数值
字符串从左到右遍历判断如下,位置指针从0开始,设置标志flag的目的是从前到后标识字符串中的每一部分是否合法:
(1)是否有正负号,有的话指针后移一位,继续往后判断,没有就跳过该步骤,继续判断
(2)如果是数字的话,指针相应后移对应的位数,将标志flag置为true,是其他的话置为false,继续往后判断
(3)如果是小数点的话,对小数点后的字符进行步骤(2)判断,返回当前flag || 小数点后步骤(2)的结果 ,继续往后判断
(此处用或连接两部分结果,因为小数点前后都可以只有一面有数字)
(4)如果是e或是E的话,返回当前flag&&e或E后面再进行步骤(1)(2)的结果
(此处用与连接两部分内容,是因为e的前后都必须要有数字,后面的数字可以带符号)
(5)如果此时flag为真,同时字符串已到了末尾,返回真,否则为假
代码如下:
public class Solution { private int index = 0; public boolean isNumeric(char[] str) { if (str.length==0) return false; boolean flag = scanInteger(str); // 如果出现'.',接下来是数字的小数部分 if (index < str.length && str[index] == '.') { index++; // 下面一行代码用||的原因: // 1. 小数可以没有整数部分,例如.123等于0.123; // 2. 小数点后面可以没有数字,例如233.等于233.0; // 3. 当然小数点前面和后面可以有数字,例如233.666 flag = scanUnsignedInteger(str) || flag; } // 如果出现'e'或者'E',接下来跟着的是数字的指数部分 if (index < str.length && (str[index] == 'E' || str[index] == 'e')) { index++; // 下面一行代码用&&的原因: // 1. 当e或E前面没有数字时,整个字符串不能表示数字,例如.e1、e1; // 2. 当e或E后面没有整数时,整个字符串不能表示数字,例如12e、12e+5.4 flag = flag && scanInteger(str); } return flag && index == str.length; } private boolean scanInteger(char[] str) { if (index < str.length && (str[index] == '+' || str[index] == '-') ) index++; return scanUnsignedInteger(str); } private boolean scanUnsignedInteger(char[] str) { int start = index; while (index < str.length && str[index] >= '0' && str[index] <= '9') index++; // 当str中存在若干0-9的数字时,返回true return start < index; } }
上面是《剑指offer》上的标准解法,好的解法总让人看起来心旷神怡,感到精妙无比。
当然,也有使用正则表达式的解法:
public class Solution { public boolean isNumeric(char[] str) { String string = String.valueOf(str); return string.matches("[\\+\\-]?\\d*(\\.\\d+)?([eE][\\+\\-]?\\d+)?"); } } /* 以下对正则进行解释: [\\+\\-]? -> 正或负符号出现与否 \\d* -> d的含义和[0-9]一样。它匹配一个数字,后缀 * 指引它可匹配零个或者多个数字,如-.34 或 +3.34均符合 (\\.\\d+)? -> 如果出现小数点,那么小数点后面必须有数字,否则一起不出现;正则表达式中 * 号表示前一个位置出现0次或多次,
-> +号表示前一个位置出现1次或多次
([eE][\\+\\-]?\\d+)? -> 如果存在指数部分,那么e或E肯定出现,+或-可以不出现, 紧接着必须跟着整数;或者整个部分都不出现
正则表达式中,^ 和 美元符号$框定正则表达式,它指引这个正则表达式对文本中的所有字符都进行匹配。如果省略这些标识,
那么只要一个字符串中包含一个数字这个正则表达式就会进行匹配。如果仅包含 ^ ,它将匹配以一个数字开头的字符串。如果仅包含$ ,则匹配以一个数字结尾的字符串。 */