力扣 每日一题 65. 有效数字
今天的是个困难题,但是不带怕的,因为前一百道我都做过了,时间久了,不记得当时是怎么做的了。
有效数字(按顺序)可以分成以下几个部分:
一个 小数 或者 整数
(可选)一个 'e' 或 'E' ,后面跟着一个 整数
小数(按顺序)可以分成以下几个部分:
(可选)一个符号字符('+' 或 '-')
下述格式之一:
至少一位数字,后面跟着一个点 '.'
至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
一个点 '.' ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
(可选)一个符号字符('+' 或 '-')
至少一位数字
部分有效数字列举如下:
["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
部分无效数字列举如下:
["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]
给你一个字符串 s ,如果 s 是一个 有效数字 ,请返回 true 。
经过分析,字符串总共可能的字符有以下几种,依次分析他们的特征。
1 点 (.),根据描述,点必须满足前面或后面有数字,并且e|E后不可以有点;
2.e|E,前面后面必须有数字,前后数字可以带+|-符号;
3.0~9,这个不需要特殊处理,如遇到数字,继续遍历即可;
4.+|-,只能在数字前,e|E之后的数字可以带正负号。
基于上述分析,我们可以设置几个变量,分别代表是否可以为该符号,如果不满足条件,直接返回false,若满足条件,一直遍历到最后,然后返回true。
1 public boolean isNumber(String s) { 2 boolean plus = true; 3 boolean minor = true; 4 boolean dot = true; 5 boolean eValue = true; 6 char[] cs = s.toCharArray(); 7 int n =cs.length; 8 for (int i = 0; i < cs.length; i++) { 9 if (((cs[i] == '+' && plus)||(cs[i] == '-' && minor))&&i<n-1&&(cs[i+1]>='0'&&cs[i+1]<='9'||cs[i+1]=='.')) { 10 plus = false; 11 minor=false; 12 } else if ((cs[i] == 'e' || cs[i] == 'E') && eValue&&i!=cs.length-1&&i!=0) { 13 eValue = false; 14 plus = true; 15 minor = true; 16 dot=false; 17 } else if (cs[i] == '.' && dot&&((i<n-1&&cs[i+1]>='0'&&cs[i+1]<='9')||(i>0&&cs[i-1]>='0'&&cs[i-1]<='9'))) { 18 dot = false; 19 } else if (cs[i] >= '0' && cs[i] <= '9') { 20 plus = false; 21 minor=false; 22 23 continue; 24 } else { 25 return false; 26 } 27 } 28 29 return true; 30 }
代码有点乱,我记得《剑指offer》上有类似的题,第20题,借鉴一下,写了个Java版本,还是比较清晰的。
1 int curr = 0; 2 public boolean isNumber(String s) { 3 s = s.trim(); 4 if (s.length() == 0) { 5 return false; 6 } 7 8 boolean isNumber = scanInteger(s); 9 if(curr<s.length()&&s.charAt(curr)=='.'){ 10 curr++; 11 isNumber = scanUnsignedInteger(s)||isNumber; 12 } 13 14 if(curr<s.length()&&(s.charAt(curr)=='E'||s.charAt(curr)=='e')){ 15 curr++; 16 isNumber = scanInteger(s)&&isNumber; 17 } 18 return isNumber&&curr==s.length(); 19 20 } 21 22 23 private boolean scanInteger(String s) { 24 if (curr < s.length() && (s.charAt(curr) == '+' || s.charAt(curr) == '-')) { 25 curr++; 26 } 27 return scanUnsignedInteger(s); 28 } 29 30 private boolean scanUnsignedInteger(String s) { 31 int tmp = curr; 32 while (curr < s.length() && s.charAt(curr) >= '0' && s.charAt(curr) <= '9') { 33 curr++; 34 } 35 return curr > tmp; 36 }