剑指offerJZ20题 表示数值的字符串 java

描述

剑指offerJZ20题 表示数值的字符串

请实现一个函数用来判断字符串str是否表示数值(包括科学计数法的数字,小数和整数)。

科学计数法的数字(按顺序)可以分成以下几个部分:

1.若干空格
2.一个整数或者小数
3.(可选)一个 ‘e’ 或 ‘E’ ,后面跟着一个整数(可正可负)
4.若干空格

小数(按顺序)可以分成以下几个部分:

1.若干空格
2.(可选)一个符号字符(‘+’ 或 ‘-’)
3. 可能是以下描述格式之一:
3.1 至少一位数字,后面跟着一个点 ‘.’
3.2 至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
3.3 一个点 ‘.’ ,后面跟着至少一位数字
4.若干空格

整数(按顺序)可以分成以下几个部分:

1.若干空格
2.(可选)一个符号字符(‘+’ 或 ‘-’)
3. 至少一位数字
4.若干空格

例如,字符串[“+100”,“5e2”,“-123”,“3.1416”,“-1E-16”]都表示数值。
但是[“12e”,“1a3.14”,“1.2.3”,“±5”,“12e+4.3”]都不是数值。

提示:
1.1 <= str.length <= 25
2.str 仅含英文字母(大写和小写),数字(0-9),加号 ‘+’ ,减号 ‘-’ ,空格 ’ ’ 或者点 ‘.’ 。
3.如果怀疑用例是不是能表示为数值的,可以使用python的print(float(str))去查看
进阶:时间复杂度O(n) ,空间复杂度O(n)

方法一:正则表达式

思路:根据正则表达式匹配字符来实现。由科学计数法中,'E’或’e’的前面为一个整数或者小数,那我们先用正则表达式实现判断整数或者小数:"\\s*[+-]?((\\d+)|((\\d*\\.\\d+)|(\\d+\\.\\d*)))(\\S)*" 然后再补充上科学计数法的后缀:([Ee][+-]?\\d+)?(\\s)*,最终表达式为: "\\s*[+-]?((\\d+)|((\\d*\\.\\d+)|(\\d+\\.\\d*)))([Ee][+-]?\\d+)?(\\s)*"
代码实现:

 import java.util.*;
 import java.util.regex.Pattern;


 public class Solution {
    /**
      * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
      *
     * 
     * @param str string字符串 
      * @return bool布尔型
      * \\s代表空,\\d代表数字, ?代表一次或零次, *代表零次或多次, +代表一次或多次, | 代表或,但要注意,他的使用规则是(a|b)必须带一个小括号, 不是只匹配挨着的两个。
     *  思路:先判断整数或小数,因为科学计数法的前面也是整数或者小数,最后加上科学计数法的后位,用?表示有或者没有
     *
      */
     public boolean isNumeric (String str) {
       String patterns = "\\s*[+-]?((\\d+)|((\\d*\\.\\d+)|(\\d+\\.\\d*)))([Ee][+-]?\\d+)?(\\s)*";
       return Pattern.matches(patterns, str);
    }
}

方法二:遍历

思路:遍历字符串,思路同样是先判断整数或小数,然后再判断科学计数法的后缀,具体逻辑和代码实现如下

import java.util.*;
public class Solution {
   
   private int pre = 0;
   
   //先过滤掉符号,再进入无符号数字的判断
   private boolean integer(String s){
       if (pre < s.length() && (s.charAt(pre) == '+' || s.charAt(pre) == '-')) pre++;
       return unsigned(s);
   }
   //判断这个字符的第一个非数字符号前面是否存在数字
   private boolean unsigned(String s){
     int temp = pre;
     while (pre < s.length() && (s.charAt(pre) <= '9' && s.charAt(pre) >= '0')) pre++;
     return pre > temp;
   }
   public boolean isNumeric (String str) {
       //判断字符串为空或者为零的情况
       if (str == null || str.length() == 0) return false;
       //得到第一个字符的下标
       while (pre < str.length() && str.charAt(pre) == ' ') pre++;
       int lat = str.length() - 1;
       //得到最后一个字符的下标的后一位
       while (lat >= 0 && str.charAt(lat) == ' ') lat--;
       lat++;
       //此处判断字符串是否全为空格
       if (lat <= pre) return false;
       //此处判断在遇到第一个非数字字符前,是否有数字(不区分有无符号)
       boolean flag = integer(str);
       //当第一个非字符为'.'时,根据小数的逻辑,'.'的前后至少有一处
       //含有数字,并且前面的数字可以带符号,后面的数字不能带符号
       //pre<lat是防止后面访问越界,如果字串全为数字则经过integer(str)后,pre = str.length(), 后续访问就会越界。
       if (pre < lat && str.charAt(pre) == '.') {
           pre++;
       //此处unsigned(str)和flag位置不能颠倒,比如字符串为"600.0"时,
       //flag为真则不会执行unsigned(str),导致pre少加一位,最后会导致
       //pre == lat 判断错误
           flag = unsigned(str) || flag;
       }
       //当遇到'e'或'E'时,符号前方可以为小数或者整数(上文已判断),符
       //号后方为整数(可以带正负号)
       if (pre < lat && (str.charAt(pre) == 'E' || str.charAt(pre) == 'e')) { 
           pre++;
           flag = flag && integer(str);
       }
       //pre == lat 用于判断遍历是否完全,排除有其他字符的情况
       return flag && (pre == lat);
       
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值