剑指 Offer 20. 表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"-1E-16"、"0123"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"及"12e+5.4"都不是。
经测验,5.0f,d,D等浮点数表示也不是
数字前后可能有空格
3.算数字
我们学习下其他人是怎么实现的吧!
1.标记+逐个遍历
设定三个标记表示数字、点、E正确地出现了
数字地正确存在为:是个数字
.的正确存在为:之前没有点且没有e
E的正确存在为:之前没有e且出现过数字,之后有数字
±的正确存在为:出现在开头或者前一位是e
时间:N
空间:1
class Solution {
public boolean isNumber(String s) {
if(s == null || s.length() == 0)
return false;
//处理开头结尾空格
s = s.trim();
//标记
boolean numFlag = false;
boolean dotFlag = false;
boolean eFlag = false;
for(int i = 0; i < s.length(); i++)
{
//判定为数字
if(Character.isDigit(s.charAt(i)))
numFlag = true;
//判定为.,之前没有点且没有e
else if(s.charAt(i) == '.' && !dotFlag && !eFlag)
dotFlag = true;
//判定为e,之前没有e且出现过数字,之后有数字
else if((s.charAt(i) == 'e' || s.charAt(i) == 'E') && !eFlag && numFlag)
{
eFlag = true;
numFlag = false;
}
//判定为+-,在字符串开头或者前一个是e
else if((s.charAt(i) == '+' || s.charAt(i) == '-') && (i == 0 || s.charAt(i - 1) == 'e' || s.charAt(i - 1) == 'E'))
{
}
else
return false;
}
//一定出现过数字
return numFlag;
}
}
2.组合判断
设一个数的表示为A.BeC或A.BEC,A为带或不带符号的整数,B为不带符号的整数或空,C为带或不带符号的整数
部分判断
时间N
空间1
class Solution {
private int index = 0;
private boolean isSignNum(String s)
{
if(s.charAt(index) == '+' || s.charAt(index) == '-')
index ++;
return isUnsignNum(s);
}
private boolean isUnsignNum(String s)
{
int pre = index;
while(Character.isDigit(s.charAt(index)))
index++;
return pre < index;
}
public boolean isNumber(String s) {
if(s == null || s.length() == 0)
return false;
//添加结束符
s = s + '|';
//跳过开头空格
while(s.charAt(index) == ' ')
index++;
//处理A部分
boolean numFlag = isSignNum(s);
//处理点
if(s.charAt(index) == '.')
{
index ++;
//小数点两边至少有一个数字
numFlag = isUnsignNum(s) || numFlag;//先处理B部分
}
//处理e和C,e两端均为数字
if(s.charAt(index) == 'e' || s.charAt(index) == 'E')
{
index++;
numFlag = numFlag && isSignNum(s);
}
//跳过结尾空格
while(s.charAt(index) == ' ')
index++;
//结尾符号
return numFlag && s.charAt(index) == '|';
}
}
3.有限状态自动机
合法的结束状态为2、3、7、8
算法流程:
初始化:
状态转移表 statesstates : 设 states[i]states[i] ,其中 ii 为所处状态, states[i]states[i] 使用哈希表存储可转移至的状态。键值对 (key, value)(key,value) 含义:若输入 keykey ,则可从状态 ii 转移至状态 valuevalue 。
当前状态 pp : 起始状态初始化为 p = 0p=0 。
状态转移循环: 遍历字符串 ss 的每个字符 cc 。
记录字符类型 tt : 分为四种情况。
当 cc 为正负号时,执行 t = ‘s’ ;
当 cc 为数字时,执行 t = ‘d’ ;
当 cc 为 e , E 时,执行 t = ‘e’ ;
当 cc 为 . , 空格 时,执行 t = c (即用字符本身表示字符类型);
否则,执行 t = ‘?’ ,代表为不属于判断范围的非法字符,后续直接返回 falsefalse 。
终止条件: 若字符类型 tt 不在哈希表 states[p]states[p] 中,说明无法转移至下一状态,因此直接返回 FalseFalse 。
状态转移: 状态 pp 转移至 states[p][t]states[p][t] 。
返回值: 跳出循环后,若状态 p \in {2, 3, 7, 8}p∈2,3,7,8 ,说明结尾合法,返回 TrueTrue ,否则返回 FalseFalse 。
class Solution {
public boolean isNumber(String s) {
Map[] states = {
new HashMap<>(){
{
put(' ', 0); put('s', 1); put('d', 2); put('.', 4);}}, //0
new HashMap<>(){
{
put('d', 2); put('.', 4);}}, //1
new HashMap<>(){
{
put('d', 2); put('.', 3); put('e', 5); put(' ', 8);}}, //2
new HashMap<>(){
{
put('d', 3); put('e', 5); put(' ', 8);}}, //3
new HashMap<>(){
{
put('d', 3); }}, //4
new HashMap<>(){
{
put('s', 6); put('d', 7); }}, //5
new HashMap<>(){
{
put('d', 7); } }, //6
new HashMap<>(){
{
put('d', 7); put(' ', 8); }}, //7
new HashMap<>(){
{
put(' ', 8); }} //8
};
int p = 0;//状态
char t; //对应字符
for(char c : s.toCharArray())
{
if(Character.isDigit(c)) t = 'd';
else if(c == ' ') t = ' ';
else if(c == '+' || c == '-') t = 's';
else if(c == 'e' || c == 'E') t = 'e';
else if(c == '.') t = '.';
else
t = '?';
if(!states[p].containsKey(t))
return false;
p = (int)states[p].get(t);
}
return p == 2 || p == 3 || p == 7 || p == 8;
}
}
确定有限状态自动机(以下简称「自动机」)是一类计算模型。它包含一系列状态,这些状态中:
有一个特殊的状态,被称作「初始状态」。
还有一系列状态被称为「接受状态」,它们组成了一个特殊的集合。其中,一个状态可能既是「初始状态」,也是「接受状态」。
起初,这个自动机处于「初始状态」。随后,它顺序地读取字符串中的每一个字符,并根据当前状态和读入的字符,按照某个事先约定好的「转移规则」,从当前状态转移到下一个状态;当状态转移完成后,它就读取下一个字符。当字符串全部读取完毕后,如果自动机处于某个「接受状态」,则判定该字符串「被接受」;否则,判定该字符串「被拒绝」。
注意:如果输入的过程中某一步转移失败了,即不存在对应的「转移规则」,此时计算将提前中止。在这种情况下我们也判定该字符串「被拒绝」。
一个自动机,总能够回答某种形式的「对于给定的输入字符串 S,判断其是否满足条件 P」的问题。在本题中,条件 P 即为「构成合法的表示数值的字符串」。
自动机驱动的编程,可以被看做一种暴力枚举方法的延伸:它穷尽了在任何一种情况下,对应任何的输入,需要做的事情。
自动机在计算机科学领域有着广泛的应用。在算法领域,它与大名鼎鼎的字符串查找算法「KMP」算法有着密切的关联;在工程领域,它是实现「正则表达式」的基础。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/solution/biao-shi-shu-zhi-de-zi-fu-chuan-by-leetcode-soluti/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。